Asterisk - The Open Source Telephony Project GIT-master-590b490
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | 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
 
#define PRE_ENCODE_POOL_MAX   200
 

Enumerations

enum  sample_type {
  SAMPLE_TYPE_CODEC = 0 , SAMPLE_TYPE_SINE , SAMPLE_TYPE_SILENCE , SAMPLE_TYPE_NOISE ,
  SAMPLE_TYPE_SPEECH
}
 

Functions

int __ast_register_translator (struct ast_translator *t, struct ast_module *mod)
 register codec translator
 
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.
 
struct ast_frameast_translate (struct ast_trans_pvt *path, struct ast_frame *f, int consume)
 do the actual translation
 
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 *dst_format, struct ast_format *src_format)
 Returns the number of steps required to convert from 'src' to 'dest'.
 
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.
 
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)
 Calculate our best translator source format, given costs, and a desired destination.
 
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.
 
void ast_translator_deactivate (struct ast_translator *t)
 Deactivate a translator.
 
void ast_translator_free_path (struct ast_trans_pvt *p)
 Frees a translator path Frees the given translator path structure.
 
int ast_unregister_translator (struct ast_translator *t)
 unregister codec translator
 
static struct ast_trans_pvtbuild_slin_to_src_path (const struct ast_translator *t)
 
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.

 
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 void generate_samples (int16_t *buf, int samples, int offset)
 Fill a buffer with samples of the selected type.
 
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_cli_translate_sampletype (struct ast_cli_entry *e, int cmd, 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 uint32_t lcg_rand (void)
 
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.
 
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.
 
static void translate_shutdown (void)
 

Variables

static unsigned int * __indextable
 table for converting index to format values.
 
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.
 
static struct ast_cli_entry cli_translate []
 
static int cur_max_index
 
static enum sample_type current_sample_type = SAMPLE_TYPE_CODEC
 
static int index_size
 
static uint32_t lcg_state = 0xdeadbeef
 
static ast_rwlock_t tablelock
 
static struct translators translators = AST_RWLIST_HEAD_INIT_VALUE
 

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

1669 { \
1670 unsigned int rate1 = ast_format_get_sample_rate(fmt1); \
1671 unsigned int rate2 = ast_format_get_sample_rate(fmt2); \
1672 (rate1 > rate2 ? rate1 - rate2 : rate2 - rate1); \
1673})

◆ GROW_INDEX

#define GROW_INDEX   16

Definition at line 149 of file translate.c.

◆ INIT_INDEX

#define INIT_INDEX   32

Definition at line 147 of file translate.c.

◆ MAX_RECALC

#define MAX_RECALC   1000

max sample recalc

Definition at line 111 of file translate.c.

◆ PRE_ENCODE_POOL_MAX

#define PRE_ENCODE_POOL_MAX   200

Maximum number of pre-encoded frames cached for non-slin benchmark sources

Definition at line 740 of file translate.c.

Enumeration Type Documentation

◆ sample_type

Enumerator
SAMPLE_TYPE_CODEC 

Default: take samples defined by codec

SAMPLE_TYPE_SINE 

Default: 1kHz sine wave

SAMPLE_TYPE_SILENCE 

All-zero frames

SAMPLE_TYPE_NOISE 

White noise via LCG PRNG

SAMPLE_TYPE_SPEECH 

Synthetic speech-like signal

Definition at line 50 of file translate.c.

50 {
51 SAMPLE_TYPE_CODEC = 0, /*!< Default: take samples defined by codec */
52 SAMPLE_TYPE_SINE, /*!< Default: 1kHz sine wave */
53 SAMPLE_TYPE_SILENCE, /*!< All-zero frames */
54 SAMPLE_TYPE_NOISE, /*!< White noise via LCG PRNG */
55 SAMPLE_TYPE_SPEECH, /*!< Synthetic speech-like signal */
56};
@ SAMPLE_TYPE_NOISE
Definition translate.c:54
@ SAMPLE_TYPE_SINE
Definition translate.c:52
@ SAMPLE_TYPE_CODEC
Definition translate.c:51
@ SAMPLE_TYPE_SILENCE
Definition translate.c:53
@ SAMPLE_TYPE_SPEECH
Definition translate.c:55

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

1512{
1513 struct ast_translator *u;
1514 char tmp[80];
1517
1519 if (!src_codec) {
1520 ast_assert(0);
1521 ast_log(LOG_WARNING, "Failed to register translator: unknown source codec %s\n", t->src_codec.name);
1522 return -1;
1523 }
1524
1526 if (!dst_codec) {
1527 ast_log(LOG_WARNING, "Failed to register translator: unknown destination codec %s\n", t->dst_codec.name);
1528 return -1;
1529 }
1530
1532 if (matrix_resize(0)) {
1533 ast_log(LOG_WARNING, "Translator matrix can not represent any more translators. Out of resources.\n");
1534 return -1;
1535 }
1538 }
1539
1540 if (!mod) {
1541 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
1542 return -1;
1543 }
1544
1545 if (!t->buf_size) {
1546 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
1547 return -1;
1548 }
1550 ast_log(LOG_WARNING, "Table cost could not be generated for %s, "
1551 "Please set table_cost variable on translator.\n", t->name);
1552 return -1;
1553 }
1554
1555 t->module = mod;
1558 t->active = 1;
1559
1560 if (t->src_fmt_index < 0 || t->dst_fmt_index < 0) {
1561 ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->src_fmt_index < 0 ? "starting" : "ending");
1562 return -1;
1563 }
1564 if (t->src_fmt_index >= cur_max_index) {
1565 ast_log(LOG_WARNING, "Source codec %s is larger than cur_max_index\n", t->src_codec.name);
1566 return -1;
1567 }
1568
1569 if (t->dst_fmt_index >= cur_max_index) {
1570 ast_log(LOG_WARNING, "Destination codec %s is larger than cur_max_index\n", t->dst_codec.name);
1571 return -1;
1572 }
1573
1574 if (t->buf_size) {
1575 /*
1576 * Align buf_size properly, rounding up to the machine-specific
1577 * alignment for pointers.
1578 */
1579 struct _test_align { void *a, *b; } p;
1580 int align = (char *)&p.b - (char *)&p.a;
1581
1582 t->buf_size = ((t->buf_size + align - 1) / align) * align;
1583 }
1584
1585 if (t->frameout == NULL) {
1587 }
1588
1590
1591 ast_verb(5, "Registered translator '%s' from codec %s to %s, table cost, %d, computational cost %d\n",
1592 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
1594
1596
1597 /* find any existing translators that provide this same srcfmt/dstfmt,
1598 and put this one in order based on computational cost */
1600 if ((u->src_fmt_index == t->src_fmt_index) &&
1601 (u->dst_fmt_index == t->dst_fmt_index) &&
1602 (u->comp_cost > t->comp_cost)) {
1604 t = NULL;
1605 break;
1606 }
1607 }
1609
1610 /* if no existing translator was found for this codec combination,
1611 add it to the beginning of the list */
1612 if (t) {
1614 }
1615
1616 matrix_rebuild(0);
1617
1619
1620 return 0;
1621}
#define ast_log
Definition astobj2.c:42
#define ao2_cleanup(obj)
Definition astobj2.h:1934
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
#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.
#define AST_RWLIST_TRAVERSE_SAFE_END
#define AST_RWLIST_INSERT_HEAD
#define AST_RWLIST_INSERT_BEFORE_CURRENT
#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
struct ast_module *int active
Definition translate.h:187
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_frame *(* frameout)(struct ast_trans_pvt *pvt)
Definition translate.h:158
struct ast_codec dst_codec
Definition translate.h:140
the list of translators
#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:152
static int add_codec2index(struct ast_codec *codec)
Definition translate.c:205
static struct ast_frame * default_frameout(struct ast_trans_pvt *pvt)
Definition translate.c:526
static void matrix_rebuild(int samples)
rebuild a translation matrix.
Definition translate.c:1040
static int matrix_resize(int init)
Definition translate.c:252
static int codec2index(struct ast_codec *codec)
Definition translate.c:182
static void generate_computational_cost(struct ast_translator *t, int seconds)
Definition translate.c:812
static int generate_table_cost(struct ast_codec *src, struct ast_codec *dst)
Definition translate.c:984
#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:981
#define ast_assert(a)
Definition utils.h:779

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_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(), and ast_codec::type.

◆ add_codec2index()

static int add_codec2index ( struct ast_codec codec)
static

Definition at line 205 of file translate.c.

206{
207 if (codec2index(codec) != -1) {
208 /* format is already already indexed */
209 return 0;
210 }
211
213 if (cur_max_index == (index_size)) {
215 return -1; /* hit max length */
216 }
217 __indextable[cur_max_index] = codec->id;
220
221 return 0;
222}
#define ast_rwlock_wrlock(a)
Definition lock.h:243
#define ast_rwlock_unlock(a)
Definition lock.h:241
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:144
static int index_size
Definition translate.c:154
static unsigned int * __indextable
table for converting index to format values.
Definition translate.c:141

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

498{
499 struct ast_frame *f = &pvt->f;
500
501 if (samples) {
502 f->samples = samples;
503 } else {
504 if (pvt->samples == 0) {
505 return NULL;
506 }
507 f->samples = pvt->samples;
508 pvt->samples = 0;
509 }
510 if (datalen) {
511 f->datalen = datalen;
512 f->data.ptr = pvt->outbuf.c;
513 } else {
514 f->datalen = pvt->datalen;
515 if (!f->datalen) {
516 f->data.ptr = NULL;
517 } else {
518 f->data.ptr = pvt->outbuf.c;
519 }
520 pvt->datalen = 0;
521 }
522
523 return ast_frisolate(f);
524}
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
Data structure associated with a single frame of data.
union ast_frame::@235 data
struct ast_frame f
Definition translate.h:215
union ast_trans_pvt::@304 outbuf
int datalen
actual space used in outbuf
Definition translate.h:218

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

624{
625 struct ast_trans_pvt *p = path;
626 struct ast_frame *out;
627 struct timeval delivery;
628 int has_timing_info;
629 long ts;
630 long len;
631 int seqno;
632
633 if (f->frametype == AST_FRAME_RTCP) {
634 /* Just pass the feedback to the right callback, if it exists.
635 * This "translation" does nothing so return a null frame. */
636 struct ast_trans_pvt *tp;
637 for (tp = p; tp; tp = tp->next) {
638 if (tp->t->feedback)
639 tp->t->feedback(tp, f);
640 }
641 return &ast_null_frame;
642 }
643
644 has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO);
645 ts = f->ts;
646 len = f->len;
647 seqno = f->seqno;
648
649 if (!ast_tvzero(f->delivery)) {
650 if (!ast_tvzero(path->nextin)) {
651 /* Make sure this is in line with what we were expecting */
652 if (!ast_tveq(path->nextin, f->delivery)) {
653 /* The time has changed between what we expected and this
654 most recent time on the new packet. If we have a
655 valid prediction adjust our output time appropriately */
656 if (!ast_tvzero(path->nextout)) {
657 path->nextout = ast_tvadd(path->nextout,
658 ast_tvsub(f->delivery, path->nextin));
659 }
660 path->nextin = f->delivery;
661 }
662 } else {
663 /* This is our first pass. Make sure the timing looks good */
664 path->nextin = f->delivery;
665 path->nextout = f->delivery;
666 }
667 /* Predict next incoming sample */
668 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(
670 }
671 delivery = f->delivery;
672 for (out = f; out && p ; p = p->next) {
673 struct ast_frame *current = out;
674
675 do {
676 framein(p, current);
678 } while (current);
679 if (out != f) {
681 }
682 out = p->t->frameout(p);
683 }
684
685 if (!out) {
687 }
688
689 if (out) {
690 /* we have a frame, play with times */
691 if (!ast_tvzero(delivery)) {
692 struct ast_frame *current = out;
693
694 do {
695 /* Regenerate prediction after a discontinuity */
696 if (ast_tvzero(path->nextout)) {
697 path->nextout = ast_tvnow();
698 }
699
700 /* Use next predicted outgoing timestamp */
701 current->delivery = path->nextout;
702
703 /* Invalidate prediction if we're entering a silence period */
704 if (current->frametype == AST_FRAME_CNG) {
705 path->nextout = ast_tv(0, 0);
706 /* Predict next outgoing timestamp from samples in this
707 frame. */
708 } else {
709 path->nextout = ast_tvadd(path->nextout, ast_samp2tv(
710 current->samples, ast_format_get_sample_rate(current->subclass.format)));
711 }
712
714 ast_debug(4, "Sample size different %d vs %d\n", f->samples, current->samples);
716 }
718 } while (current);
719 } else {
720 out->delivery = ast_tv(0, 0);
722 if (has_timing_info) {
723 out->ts = ts;
724 out->len = len;
725 out->seqno = seqno;
726 }
727 /* Invalidate prediction if we're entering a silence period */
728 if (out->frametype == AST_FRAME_CNG) {
729 path->nextout = ast_tv(0, 0);
730 }
731 }
732 }
733 if (consume) {
734 ast_frfree(f);
735 }
736 return out;
737}
size_t current
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_frfree(fr)
@ AST_FRFLAG_HAS_TIMING_INFO
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.
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:2280
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition extconf.c:2295
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:594
static int framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
framein wrapper, deals with bound checks.
Definition translate.c:454
FILE * out
Definition utils/frame.c:33
#define ast_test_flag(p, flag)
Definition utils.h:64
#define ast_set2_flag(p, value, flag)
Definition utils.h:95
#define ast_clear_flag(p, flag)
Definition utils.h:78

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

1891{
1892 struct ast_format *cur_dest, *cur_src;
1893 int index;
1894
1895 for (index = 0; index < ast_format_cap_count(dest); ++index) {
1896 if (!(cur_dest = ast_format_cap_get_format(dest, index))) {
1897 continue;
1898 }
1899
1900 /* We give preference to a joint format structure if possible */
1901 if ((cur_src = ast_format_cap_get_compatible_format(src, cur_dest))) {
1902 ast_format_cap_append(result, cur_src, 0);
1903 ao2_ref(cur_src, -1);
1904 } else {
1905 /* Otherwise we just use the destination format */
1906 ast_format_cap_append(result, cur_dest, 0);
1907 }
1908 ao2_ref(cur_dest, -1);
1909 }
1910
1911 /* if we don't have a source format, we just have to try all
1912 possible destination formats */
1913 if (!src) {
1914 return;
1915 }
1916
1917 for (index = 0; index < ast_format_cap_count(src); ++index) {
1918 if (!(cur_src = ast_format_cap_get_format(src, index))) {
1919 continue;
1920 }
1921
1923 check_translation_path(dest, src, result,
1924 cur_src, AST_MEDIA_TYPE_AUDIO);
1925 check_translation_path(dest, src, result,
1926 cur_src, AST_MEDIA_TYPE_VIDEO);
1928 ao2_ref(cur_src, -1);
1929 }
1930}
#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:1832

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

1950{
1951 int res = 0;
1953 res = matrix_resize(1);
1956 return res;
1957}
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:231
static void translate_shutdown(void)
Definition translate.c:1932
static struct ast_cli_entry cli_translate[]
Definition translate.c:1505
#define ARRAY_LEN(a)
Definition utils.h:706

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

1811{
1812 unsigned int res = -1;
1813 /* convert bitwise format numbers into array indices */
1814 int src = format2index(src_format);
1815 int dest = format2index(dst_format);
1816
1817 if (src < 0 || dest < 0) {
1818 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src < 0 ? "starting" : "ending");
1819 return -1;
1820 }
1822
1823 if (matrix_get(src, dest)->step) {
1824 res = matrix_get(src, dest)->multistep + 1;
1825 }
1826
1828
1829 return res;
1830}
uint8_t multistep
Definition translate.c:120
static struct translator_path * matrix_get(unsigned int x, unsigned int y)
Definition translate.c:340
static int format2index(struct ast_format *format)
Definition translate.c:191

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

1146{
1147 if (!p || !p->t) {
1148 return "";
1149 }
1150
1153 while (p) {
1154 ast_str_append(str, 0, "->");
1156 p = p->next;
1157 }
1158
1159 return ast_str_buffer(*str);
1160}
const char * str
Definition app_jack.c:150
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
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
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
static void codec_append_name(const struct ast_codec *codec, struct ast_str **buf)
Definition translate.c:1136

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

1653{
1655 t->active = 1;
1656 matrix_rebuild(0);
1658}

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

1680{
1681 unsigned int besttablecost = INT_MAX;
1682 unsigned int beststeps = INT_MAX;
1683 struct ast_format *fmt;
1684 struct ast_format *dst;
1685 struct ast_format *src;
1686 RAII_VAR(struct ast_format *, best, NULL, ao2_cleanup);
1687 RAII_VAR(struct ast_format *, bestdst, NULL, ao2_cleanup);
1688 struct ast_format_cap *joint_cap;
1689 int i;
1690 int j;
1691
1692 if (ast_format_cap_empty(dst_cap) || ast_format_cap_empty(src_cap)) {
1693 ast_log(LOG_ERROR, "Cannot determine best translation path since one capability supports no formats\n");
1694 return -1;
1695 }
1696
1698 if (!joint_cap) {
1699 return -1;
1700 }
1701 ast_format_cap_get_compatible(dst_cap, src_cap, joint_cap);
1702
1703 for (i = 0; i < ast_format_cap_count(joint_cap); ++i, ao2_cleanup(fmt)) {
1704 fmt = ast_format_cap_get_format(joint_cap, i);
1705 if (!fmt
1707 continue;
1708 }
1709
1710 if (!best
1712 ao2_replace(best, fmt);
1713 }
1714 }
1715 ao2_ref(joint_cap, -1);
1716
1717 if (best) {
1718 ao2_replace(*dst_fmt_out, best);
1719 ao2_replace(*src_fmt_out, best);
1720 return 0;
1721 }
1722
1723 /* need to translate */
1725 for (i = 0; i < ast_format_cap_count(dst_cap); ++i, ao2_cleanup(dst)) {
1726 dst = ast_format_cap_get_format(dst_cap, i);
1727 if (!dst
1729 continue;
1730 }
1731
1732 for (j = 0; j < ast_format_cap_count(src_cap); ++j, ao2_cleanup(src)) {
1733 int x;
1734 int y;
1735
1736 src = ast_format_cap_get_format(src_cap, j);
1737 if (!src
1739 continue;
1740 }
1741
1742 x = format2index(src);
1743 y = format2index(dst);
1744 if (x < 0 || y < 0) {
1745 continue;
1746 }
1747 if (!matrix_get(x, y) || !(matrix_get(x, y)->step)) {
1748 continue;
1749 }
1750 if (matrix_get(x, y)->table_cost < besttablecost
1751 || matrix_get(x, y)->multistep < beststeps) {
1752 /* better than what we have so far */
1753 ao2_replace(best, src);
1754 ao2_replace(bestdst, dst);
1755 besttablecost = matrix_get(x, y)->table_cost;
1756 beststeps = matrix_get(x, y)->multistep;
1757 } else if (matrix_get(x, y)->table_cost == besttablecost
1758 && matrix_get(x, y)->multistep == beststeps) {
1759 int replace = 0;
1760 unsigned int gap_selected = format_sample_rate_absdiff(best, bestdst);
1761 unsigned int gap_current = format_sample_rate_absdiff(src, dst);
1762
1763 if (gap_current < gap_selected) {
1764 /* better than what we have so far */
1765 replace = 1;
1766 } else if (gap_current == gap_selected) {
1767 int src_quality, best_quality;
1768 struct ast_codec *src_codec, *best_codec;
1769
1770 src_codec = ast_format_get_codec(src);
1771 best_codec = ast_format_get_codec(best);
1772 src_quality = src_codec->quality;
1773 best_quality = best_codec->quality;
1774
1775 ao2_cleanup(src_codec);
1776 ao2_cleanup(best_codec);
1777
1778 /* We have a tie, so choose the format with the higher quality, if they differ. */
1779 if (src_quality > best_quality) {
1780 /* Better than what we had before. */
1781 replace = 1;
1782 ast_debug(2, "Tiebreaker: preferring format %s (%d) to %s (%d)\n", ast_format_get_name(src), src_quality,
1783 ast_format_get_name(best), best_quality);
1784 } else {
1785 /* This isn't necessarily indicative of a problem, but in reality this shouldn't really happen, unless
1786 * there are 2 formats that are basically the same. */
1787 ast_debug(1, "Completely ambiguous tie between formats %s and %s (quality %d): sticking with %s, but this is arbitrary\n",
1788 ast_format_get_name(src), ast_format_get_name(best), best_quality, ast_format_get_name(best));
1789 }
1790 }
1791 if (replace) {
1792 ao2_replace(best, src);
1793 ao2_replace(bestdst, dst);
1794 besttablecost = matrix_get(x, y)->table_cost;
1795 beststeps = matrix_get(x, y)->multistep;
1796 }
1797 }
1798 }
1799 }
1801
1802 if (!best) {
1803 return -1;
1804 }
1805 ao2_replace(*dst_fmt_out, bestdst);
1806 ao2_replace(*src_fmt_out, best);
1807 return 0;
1808}
#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)
#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:118
#define format_sample_rate_absdiff(fmt1, fmt2)
Definition translate.c:1669

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

544{
545 struct ast_trans_pvt *head = NULL, *tail = NULL;
546 int src_index, dst_index;
547
548 src_index = format2index(src);
549 dst_index = format2index(dst);
550
551 if (src_index < 0 || dst_index < 0) {
552 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src_index < 0 ? "starting" : "ending");
553 return NULL;
554 }
555
557
558 while (src_index != dst_index) {
559 struct ast_trans_pvt *cur;
560 struct ast_format *explicit_dst = NULL;
561 struct ast_translator *t = matrix_get(src_index, dst_index)->step;
562 if (!t) {
563 ast_log(LOG_WARNING, "No translator path from %s to %s\n",
567 return NULL;
568 }
570 explicit_dst = dst;
571 }
572 if (!(cur = newpvt(t, explicit_dst))) {
573 ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n",
577 return NULL;
578 }
579 if (!head) {
580 head = cur;
581 } else {
582 tail->next = cur;
583 }
584 tail = cur;
585 cur->nextin = cur->nextout = ast_tv(0, 0);
586 /* Keep going if this isn't the final destination */
587 src_index = cur->t->dst_fmt_index;
588 }
589
591 return head;
592}
struct ast_translator * step
Definition translate.c:117
void ast_translator_free_path(struct ast_trans_pvt *p)
Frees a translator path Frees the given translator path structure.
Definition translate.c:533
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:369

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

1661{
1663 t->active = 0;
1664 matrix_rebuild(0);
1666}

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

1625{
1626 char tmp[80];
1627 struct ast_translator *u;
1628 int found = 0;
1629
1632 if (u == t) {
1634 ast_verb(5, "Unregistered translator '%s' from codec %s to %s\n",
1635 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
1636 t->src_codec.name, t->dst_codec.name);
1637 found = 1;
1638 break;
1639 }
1640 }
1642
1643 if (found && !ast_shutting_down()) {
1644 matrix_rebuild(0);
1645 }
1646
1648
1649 return (u ? 0 : -1);
1650}
int ast_shutting_down(void)
Definition asterisk.c:1889
#define AST_RWLIST_REMOVE_CURRENT
struct ast_translator::@303 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, and term_color().

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

◆ build_slin_to_src_path()

static struct ast_trans_pvt * build_slin_to_src_path ( const struct ast_translator t)
static

Definition at line 751 of file translate.c.

752{
753 struct ast_trans_pvt *head = NULL, *tail = NULL;
754 struct ast_codec *slin_codec;
755 int slin_index, dst_index;
756
757 if (!strcmp(t->src_codec.name, "slin")) {
758 return NULL; /* source is already slin, no pre-encoding needed */
759 }
760
761 slin_codec = ast_codec_get("slin", AST_MEDIA_TYPE_AUDIO, 8000);
762 if (!slin_codec) {
763 return NULL;
764 }
765
766 slin_index = codec2index(slin_codec);
767 ao2_ref(slin_codec, -1);
768
769 if (slin_index < 0) {
770 return NULL;
771 }
772
773 dst_index = t->src_fmt_index;
774 if (dst_index < 0 || slin_index == dst_index) {
775 return NULL;
776 }
777
778 while (slin_index != dst_index) {
779 struct ast_trans_pvt *cur;
780 struct ast_translator *step = matrix_get(slin_index, dst_index)->step;
781 if (!step) {
783 return NULL;
784 }
785 cur = newpvt(step, NULL);
786 if (!cur) {
788 return NULL;
789 }
790 if (!head) {
791 head = cur;
792 } else {
793 tail->next = cur;
794 }
795 tail = cur;
796 cur->nextin = cur->nextout = ast_tv(0, 0);
797 slin_index = cur->t->dst_fmt_index;
798 }
799
800 return head;
801}

References ao2_ref, ast_codec_get(), AST_MEDIA_TYPE_AUDIO, ast_translator_free_path(), ast_tv(), codec2index(), ast_translator::dst_fmt_index, matrix_get(), ast_codec::name, newpvt(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, NULL, ast_translator::src_codec, ast_translator::src_fmt_index, translator_path::step, and ast_trans_pvt::t.

Referenced by generate_computational_cost().

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

1836{
1837 int i;
1838
1839 if (ast_format_get_type(src_fmt) != type) {
1840 return;
1841 }
1842
1843 /* For a given source format, traverse the list of
1844 known formats to determine whether there exists
1845 a translation path from the source format to the
1846 destination format. */
1847 for (i = ast_format_cap_count(result) - 1; 0 <= i; i--) {
1848 int index, src_index;
1850
1851 if (ast_format_get_type(fmt) != type) {
1852 continue;
1853 }
1854
1855 /* if this is not a desired format, nothing to do */
1857 continue;
1858 }
1859
1860 /* if the source is supplying this format, then
1861 we can leave it in the result */
1863 continue;
1864 }
1865
1866 /* if this is a pass-through format, not in the source,
1867 we cannot transcode. Therefore, remove it from the result */
1868 src_index = format2index(src_fmt);
1869 index = format2index(fmt);
1870 if (src_index < 0 || index < 0) {
1872 continue;
1873 }
1874
1875 /* if we don't have a translation path from the src
1876 to this format, remove it from the result */
1877 if (!matrix_get(src_index, index)->step) {
1879 continue;
1880 }
1881
1882 /* now check the opposite direction */
1883 if (!matrix_get(index, src_index)->step) {
1885 }
1886 }
1887
1888}
static const char type[]
@ 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 182 of file translate.c.

183{
184 return codec_to_index(codec->id);
185}
static int codec_to_index(unsigned int id)
Definition translate.c:162

References codec_to_index(), and ast_codec::id.

Referenced by __ast_register_translator(), add_codec2index(), build_slin_to_src_path(), 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 1136 of file translate.c.

1137{
1138 if (codec) {
1139 ast_str_append(buf, 0, "(%s@%u)", codec->name, codec->sample_rate);
1140 } else {
1141 ast_str_append(buf, 0, "(nothing)");
1142 }
1143}
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 162 of file translate.c.

163{
164 int x;
165
167 for (x = 0; x < cur_max_index; x++) {
168 if (__indextable[x] == id) {
169 /* format already exists in index2format table */
171 return x;
172 }
173 }
175 return -1; /* not found */
176}
#define ast_rwlock_rdlock(a)
Definition lock.h:242

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

1163{
1164 int i = 1;
1165 int wordlen = strlen(word);
1166 struct ast_codec *codec;
1167
1168 while ((codec = ast_codec_get_by_id(i))) {
1169 ++i;
1170 if (codec->type != AST_MEDIA_TYPE_AUDIO) {
1171 ao2_ref(codec, -1);
1172 continue;
1173 }
1174 if (!strncasecmp(word, codec->name, wordlen)) {
1175 if (ast_cli_completion_add(ast_strdup(codec->name))) {
1176 ao2_ref(codec, -1);
1177 break;
1178 }
1179 }
1180 ao2_ref(codec, -1);
1181 }
1182
1183 return NULL;
1184}
#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:2845
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 526 of file translate.c.

527{
528 return ast_trans_frameout(pvt, 0, 0);
529}
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:496

References ast_trans_frameout().

Referenced by __ast_register_translator().

◆ destroy()

static void destroy ( struct ast_trans_pvt pvt)
static

Definition at line 349 of file translate.c.

350{
351 struct ast_translator *t = pvt->t;
352
353 if (t->destroy) {
354 t->destroy(pvt);
355 }
357 if (pvt->explicit_dst) {
358 ao2_ref(pvt->explicit_dst, -1);
359 pvt->explicit_dst = NULL;
360 }
361 ast_free(pvt);
362 ast_module_unref(t->module);
363}
#define ast_free(a)
Definition astmm.h:180
#define ast_module_unref(mod)
Release a reference to the module.
Definition module.h:483
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, 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 191 of file translate.c.

192{
194}
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 454 of file translate.c.

455{
456 /* Copy the last in jb timing info to the pvt */
458 pvt->f.ts = f->ts;
459 pvt->f.len = f->len;
460 pvt->f.seqno = f->seqno;
461
462 if (f->samples == 0) {
463 /* Do not log empty audio frame */
464 if (!f->src || strcasecmp(f->src, "ast_prod")) {
465 ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
466 }
467 }
468 if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */
469 int src_srate = pvt->t->src_codec.sample_rate;
470 int dst_srate = pvt->t->dst_codec.sample_rate;
471
472 ast_assert(src_srate > 0);
473
474 if (f->datalen == 0) { /* perform native PLC if available */
475 /* If the codec has native PLC, then do that */
476 if (!pvt->t->native_plc)
477 return 0;
478 }
479
480 if (pvt->samples + (f->samples * dst_srate / src_srate) > pvt->t->buffer_samples) {
481 ast_log(LOG_WARNING, "Out of buffer space\n");
482 return -1;
483 }
484 }
485 /* we require a framein routine, wouldn't know how to do
486 * it otherwise.
487 */
488 return pvt->t->framein(pvt, f);
489}
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:85

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

813{
814 int num_samples = 0;
815 struct ast_trans_pvt *pvt;
816 struct rusage start;
817 struct rusage end;
818 int cost;
819 int out_rate = t->dst_codec.sample_rate;
820 struct ast_frame **pre_pool = NULL;
821 int pre_pool_count = 0;
822 int pre_pool_idx = 0;
823 int use_pre_pool = 0;
824
825 if (!seconds) {
826 seconds = 1;
827 }
828
829 /* If they don't make samples, give them a terrible score */
830 if (!t->sample) {
831 ast_debug(3, "Translator '%s' does not produce sample frames.\n", t->name);
832 t->comp_cost = 999999;
833 return;
834 }
835
836 pvt = newpvt(t, NULL);
837 if (!pvt) {
838 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
839 t->comp_cost = 999999;
840 return;
841 }
842
843 /*
844 * For non-CODEC sample types, pre-generate frames before starting the
845 * timer so sample-generation overhead is excluded from the measurement.
846 *
847 * For slin sources: isolate a fresh copy of each generated frame directly.
848 * For non-slin sources: route the generated slin frames through a
849 * slin->src_codec encoding path first. If no such path exists in the
850 * current matrix, use_pre_pool stays 0 and we fall back to t->sample().
851 */
853 int16_t slin_buf[80];
854 struct ast_frame slin_f;
855 struct ast_trans_pvt *pre_path = NULL;
856 int attempt;
857
858 if (strcmp(t->src_codec.name, "slin")) {
859 pre_path = build_slin_to_src_path(t);
860 }
861
862 if (!strcmp(t->src_codec.name, "slin") || pre_path) {
863 pre_pool = ast_malloc(PRE_ENCODE_POOL_MAX * sizeof(*pre_pool));
864 if (pre_pool) {
865 memset(&slin_f, 0, sizeof(slin_f));
866 slin_f.frametype = AST_FRAME_VOICE;
867 slin_f.datalen = sizeof(slin_buf);
868 slin_f.samples = ARRAY_LEN(slin_buf);
869 slin_f.data.ptr = slin_buf;
870 slin_f.src = __PRETTY_FUNCTION__;
871 slin_f.subclass.format = ast_format_slin;
872
873 for (attempt = 0; pre_pool_count < PRE_ENCODE_POOL_MAX; attempt++) {
874 struct ast_frame *out;
875
876 if (attempt >= PRE_ENCODE_POOL_MAX * 10) {
877 break; /* encoder not producing output; give up */
878 }
879
880 generate_samples(slin_buf, ARRAY_LEN(slin_buf),
881 attempt * (int)ARRAY_LEN(slin_buf));
882
883 if (pre_path) {
884 /* non-slin: encode through the pre_path chain */
885 struct ast_trans_pvt *pp;
886 out = &slin_f;
887 for (pp = pre_path; pp; pp = pp->next) {
888 struct ast_frame *next_out;
889 framein(pp, out);
890 if (out != &slin_f) {
892 }
893 next_out = pp->t->frameout(pp);
894 out = next_out;
895 if (!out) {
896 break;
897 }
898 }
899 } else {
900 /* slin: isolate a standalone copy of the frame */
902 }
903
904 if (out) {
905 pre_pool[pre_pool_count++] = out;
906 }
907 }
908 use_pre_pool = (pre_pool_count > 0);
909 }
910 ast_translator_free_path(pre_path);
911 }
912 }
913
914 getrusage(RUSAGE_SELF, &start);
915
916 /* Call the encoder until we've processed the required number of samples */
917 while (num_samples < seconds * out_rate) {
918 struct ast_frame *f;
919
920 if (use_pre_pool) {
921 /* cycle through the pre-generated frame pool */
922 framein(pvt, pre_pool[pre_pool_idx % pre_pool_count]);
923 pre_pool_idx++;
924 } else {
925 /* default: use the codec's own sample generator */
926 f = t->sample();
927 if (!f) {
928 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
929 destroy(pvt);
930 t->comp_cost = 999999;
931 goto cleanup;
932 }
933 framein(pvt, f);
934 ast_frfree(f);
935 }
936
937 while ((f = t->frameout(pvt))) {
938 num_samples += f->samples;
939 ast_frfree(f);
940 }
941 }
942
943 getrusage(RUSAGE_SELF, &end);
944
945 cost = ((end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000) + end.ru_utime.tv_usec - start.ru_utime.tv_usec;
946 cost += ((end.ru_stime.tv_sec - start.ru_stime.tv_sec) * 1000000) + end.ru_stime.tv_usec - start.ru_stime.tv_usec;
947
948 destroy(pvt);
949
950 t->comp_cost = cost / seconds;
951
952 if (!t->comp_cost) {
953 t->comp_cost = 1;
954 }
955
956cleanup:
957 if (pre_pool) {
958 int i;
959 for (i = 0; i < pre_pool_count; i++) {
960 ast_frfree(pre_pool[i]);
961 }
962 ast_free(pre_pool);
963 }
964}
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
char * end
Definition eagi_proxy.c:73
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
static struct ast_format_def slin_f
Definition format_sln.c:128
static void cleanup(void)
Clean up any old apps that we don't need any more.
Definition res_stasis.c:327
struct ast_format * format
Definition mod_format.h:48
struct ast_frame *(* sample)(void)
Definition translate.h:170
static struct ast_trans_pvt * build_slin_to_src_path(const struct ast_translator *t)
Definition translate.c:751
#define PRE_ENCODE_POOL_MAX
Definition translate.c:740
static enum sample_type current_sample_type
Definition translate.c:58
static void generate_samples(int16_t *buf, int samples, int offset)
Fill a buffer with samples of the selected type.
Definition translate.c:74

References ARRAY_LEN, ast_debug, ast_format_slin, AST_FRAME_VOICE, ast_free, ast_frfree, ast_frisolate, ast_log, ast_malloc, ast_translator_free_path(), build_slin_to_src_path(), cleanup(), ast_translator::comp_cost, current_sample_type, destroy(), ast_translator::dst_codec, end, ast_format_def::format, framein(), ast_translator::frameout, generate_samples(), LOG_WARNING, ast_codec::name, ast_translator::name, newpvt(), ast_trans_pvt::next, NULL, out, PRE_ENCODE_POOL_MAX, ast_trans_pvt::pvt, ast_translator::sample, ast_codec::sample_rate, SAMPLE_TYPE_CODEC, ast_frame::samples, slin_f, ast_translator::src_codec, and ast_trans_pvt::t.

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

595{
596 struct ast_frame res = { AST_FRAME_VOICE };
597
598 /*
599 * If we've gotten here then we should have an interpolated frame that was not handled
600 * by the translation codec. So create an interpolated frame in the appropriate format
601 * that was going to be written. This frame might be handled later by other resources.
602 * For instance, generic plc.
603 *
604 * Note, generic plc is currently only available for the format type 'slin' (8KHz only -
605 * The generic plc code appears to have been based around that). Generic plc is filled
606 * in later on frame write.
607 */
608 if (!ast_opt_generic_plc || f->datalen != 0 ||
610 return NULL;
611 }
612
613 res.subclass.format = ast_format_cache_get_slin_by_rate(8000); /* ref bumped on dup */
614 res.samples = f->samples;
615 res.datalen = 0;
616 res.data.ptr = NULL;
618
619 return ast_frdup(&res);
620}
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_cache_get_slin_by_rate(unsigned int rate)
Retrieve the best signed linear format given a sample rate.
#define ast_frdup(fr)
Copies a frame.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
#define ast_opt_generic_plc
Definition options.h:144

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_samples()

static void generate_samples ( int16_t *  buf,
int  samples,
int  offset 
)
static

Fill a buffer with samples of the selected type.

Parameters
bufOutput sample buffer (int16_t)
samplesNumber of samples to generate
offsetRunning sample offset (for continuous sample types)

Definition at line 74 of file translate.c.

75{
76 int i;
77 switch (current_sample_type) {
79 memset(buf, 0, samples * sizeof(int16_t));
80 break;
82 for (i = 0; i < samples; i++) {
83 buf[i] = (int16_t)(lcg_rand() & 0xFFFF);
84 }
85 break;
87 /* Synthetic speech approximation: mix of two sine waves
88 * (fundamental ~200Hz + harmonic ~800Hz) with slow AM envelope,
89 * loosely inspired by ITU-T P.50 artificial voice. */
90 for (i = 0; i < samples; i++) {
91 double t = (double)(offset + i) / 8000.0;
92 double sig = 0.6 * sin(2.0 * M_PI * 200.0 * t)
93 + 0.4 * sin(2.0 * M_PI * 800.0 * t);
94 /* Slow AM at 4Hz to simulate syllable rhythm */
95 sig *= 0.5 * (1.0 + sin(2.0 * M_PI * 4.0 * t));
96 buf[i] = (int16_t)(sig * 16000.0);
97 }
98 break;
100 default:
101 /* pure 1kHz sine wave */
102 for (i = 0; i < samples; i++) {
103 buf[i] = (int16_t)(sin(2.0 * M_PI * 1000.0 *
104 (double)(offset + i) / 8000.0) * 16000.0);
105 }
106 break;
107 }
108}
#define M_PI
Definition resample.c:83
static uint32_t lcg_rand(void)
Definition translate.c:62

References buf, current_sample_type, lcg_rand(), M_PI, SAMPLE_TYPE_NOISE, SAMPLE_TYPE_SILENCE, SAMPLE_TYPE_SINE, and SAMPLE_TYPE_SPEECH.

Referenced by generate_computational_cost().

◆ generate_table_cost()

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

Definition at line 984 of file translate.c.

985{
986 int src_rate = src->sample_rate;
987 int src_ll = 0;
988 int dst_rate = dst->sample_rate;
989 int dst_ll = 0;
990
991 if ((src->type != AST_MEDIA_TYPE_AUDIO) ||
992 (dst->type != AST_MEDIA_TYPE_AUDIO)) {
993 /* This method of generating table cost is limited to audio.
994 * Translators for media other than audio must manually set their
995 * table cost. */
996 return 0;
997 }
998
999 src_ll = !strcmp(src->name, "slin");
1000 dst_ll = !strcmp(dst->name, "slin");
1001 if (src_ll) {
1002 if (dst_ll && (src_rate == dst_rate)) {
1004 } else if (!dst_ll && (src_rate == dst_rate)) {
1006 } else if (dst_ll && (src_rate < dst_rate)) {
1008 } else if (!dst_ll && (src_rate < dst_rate)) {
1010 } else if (dst_ll && (src_rate > dst_rate)) {
1012 } else if (!dst_ll && (src_rate > dst_rate)) {
1014 } else {
1016 }
1017 } else {
1018 if (dst_ll && (src_rate == dst_rate)) {
1020 } else if (!dst_ll && (src_rate == dst_rate)) {
1022 } else if (dst_ll && (src_rate < dst_rate)) {
1024 } else if (!dst_ll && (src_rate < dst_rate)) {
1026 } else if (dst_ll && (src_rate > dst_rate)) {
1028 } else if (!dst_ll && (src_rate > dst_rate)) {
1030 } else {
1032 }
1033 }
1034}
@ 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 1390 of file translate.c.

1391{
1392 static const char * const option[] = { "recalc", "paths", "comp", NULL };
1393
1394 switch (cmd) {
1395 case CLI_INIT:
1396 e->command = "core show translation";
1397 e->usage =
1398 "Usage: 'core show translation' can be used in three ways.\n"
1399 " 1. 'core show translation [recalc [<recalc seconds>]\n"
1400 " Displays known codec translators and the cost associated\n"
1401 " with each conversion. If the argument 'recalc' is supplied along\n"
1402 " with optional number of seconds to test a new test will be performed\n"
1403 " as the chart is being displayed.\n"
1404 " 2. 'core show translation paths [codec [sample_rate]]'\n"
1405 " This will display all the translation paths associated with a codec.\n"
1406 " If a codec has multiple sample rates, the sample rate must be\n"
1407 " provided as well.\n"
1408 " 3. 'core show translation comp [<recalc seconds>]'\n"
1409 " Displays known codec translators and the cost associated\n"
1410 " with each conversion. If the argument 'recalc' is supplied along\n"
1411 " with optional number of seconds to test a new test will be performed\n"
1412 " as the chart is being displayed. The resulting numbers in the table\n"
1413 " give the actual computational costs in microseconds.\n";
1414 return NULL;
1415 case CLI_GENERATE:
1416 if (a->pos == 3) {
1417 return ast_cli_complete(a->word, option, -1);
1418 }
1419 if (a->pos == 4 && !strcasecmp(a->argv[3], option[1])) {
1420 return complete_trans_path_choice(a->word);
1421 }
1422 /* BUGBUG - add tab completion for sample rates */
1423 return NULL;
1424 }
1425
1426 if (a->argc > 6)
1427 return CLI_SHOWUSAGE;
1428
1429 if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 5) { /* show paths */
1430 return handle_show_translation_path(a, a->argv[4], 0);
1431 } else if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 6) {
1432 unsigned int sample_rate;
1433 if (sscanf(a->argv[5], "%30u", &sample_rate) != 1) {
1434 ast_cli(a->fd, "Invalid sample rate: %s.\n", a->argv[5]);
1435 return CLI_FAILURE;
1436 }
1437 return handle_show_translation_path(a, a->argv[4], sample_rate);
1438 } 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 */
1440 } else if (a->argc > 3) { /* wrong input */
1441 return CLI_SHOWUSAGE;
1442 }
1443
1445}
#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:1931
@ 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:1205
static void handle_cli_recalc(struct ast_cli_args *a)
Definition translate.c:1186
static char * handle_show_translation_path(struct ast_cli_args *a, const char *codec_name, unsigned int sample_rate)
Definition translate.c:1325
static char * complete_trans_path_choice(const char *word)
Definition translate.c:1162

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

1187{
1188 int time = a->argv[4] ? atoi(a->argv[4]) : 1;
1189
1190 if (time <= 0) {
1191 ast_cli(a->fd, " Recalc must be greater than 0. Defaulting to 1.\n");
1192 time = 1;
1193 }
1194
1195 if (time > MAX_RECALC) {
1196 ast_cli(a->fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", time - MAX_RECALC, MAX_RECALC);
1197 time = MAX_RECALC;
1198 }
1199 ast_cli(a->fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", time);
1201 matrix_rebuild(time);
1203}
#define MAX_RECALC
Definition translate.c:111

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

Referenced by handle_cli_core_show_translation().

◆ handle_cli_translate_sampletype()

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

Definition at line 1447 of file translate.c.

1449{
1450 static const char * const types[] = { "codec", "sine", "silence", "noise", "speech", NULL };
1451
1452 switch (cmd) {
1453 case CLI_INIT:
1454 e->command = "translate sampletype";
1455 e->usage =
1456 "Usage: translate sampletype [codec|sine|silence|noise|speech]\n"
1457 " Get or set the sample type used for codec matrix cost\n"
1458 " computation. Default is 'codec'.\n"
1459 " codec - samples defined inside codec\n"
1460 " sine - 1kHz sine wave\n"
1461 " silence - All-zero frames\n"
1462 " noise - White noise\n"
1463 " speech - Synthetic speech-like signal (P.50 inspired)\n";
1464 return NULL;
1465 case CLI_GENERATE:
1466 return ast_cli_complete(a->word, types, a->n);
1467 }
1468
1469 if (a->argc == 2) {
1470 /* Query current setting */
1471 const char *names[] = { "codec", "sine", "silence", "noise", "speech" };
1472 ast_cli(a->fd, "Current translate sample type: %s\n",
1473 names[current_sample_type]);
1474 return CLI_SUCCESS;
1475 }
1476
1477 if (a->argc != 3)
1478 return CLI_SHOWUSAGE;
1479
1480 if (!strcasecmp(a->argv[2], "silence")) {
1482 } else if (!strcasecmp(a->argv[2], "noise")) {
1484 } else if (!strcasecmp(a->argv[2], "speech")) {
1486 } else if (!strcasecmp(a->argv[2], "sine")) {
1488 } else if (!strcasecmp(a->argv[2], "codec")) {
1490 } else {
1491 ast_cli(a->fd, "Unknown sample type '%s'. Use: codec, sine, silence, noise, speech\n",
1492 a->argv[2]);
1493 return CLI_SHOWUSAGE;
1494 }
1495
1496 /* Rebuild the matrix with the new sample type */
1497 ast_cli(a->fd, "Sample type set to '%s'. Rebuilding codec matrix...\n", a->argv[2]);
1499 matrix_rebuild(1);
1501
1502 return CLI_SUCCESS;
1503}
#define CLI_SUCCESS
Definition cli.h:44

References a, ast_cli(), ast_cli_complete(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, current_sample_type, matrix_rebuild(), NULL, SAMPLE_TYPE_CODEC, SAMPLE_TYPE_NOISE, SAMPLE_TYPE_SILENCE, SAMPLE_TYPE_SINE, SAMPLE_TYPE_SPEECH, and ast_cli_entry::usage.

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

1326{
1327 int i = 1;
1328 struct ast_str *str = ast_str_alloca(1024);
1329 struct ast_translator *step;
1330 struct ast_codec *dst_codec;
1331 struct ast_codec *src_codec = ast_codec_get(codec_name, AST_MEDIA_TYPE_AUDIO, sample_rate);
1332
1333 if (!src_codec) {
1334 ast_cli(a->fd, "Source codec \"%s\" is not found.\n", codec_name);
1335 return CLI_FAILURE;
1336 }
1337
1339 ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %u ---\n",
1340 codec_name, src_codec->sample_rate);
1341
1342 while ((dst_codec = ast_codec_get_by_id(i))) {
1343 int src, dst;
1344 char src_buffer[64];
1345 char dst_buffer[64];
1346
1347 ++i;
1348 if (src_codec == dst_codec ||
1349 dst_codec->type != AST_MEDIA_TYPE_AUDIO) {
1350 ao2_ref(dst_codec, -1);
1351 continue;
1352 }
1353
1354 dst = codec2index(dst_codec);
1355 src = codec2index(src_codec);
1356
1357 if (src < 0 || dst < 0) {
1358 ast_str_set(&str, 0, "No Translation Path");
1359 } else {
1360 step = matrix_get(src, dst)->step;
1361
1362 if (step) {
1364 while (src != dst) {
1365 src = step->dst_fmt_index;
1366 step = matrix_get(src, dst)->step;
1367 if (!step) {
1368 ast_str_append(&str, 0, "->");
1369 codec_append_name(dst_codec, &str);
1370 break;
1371 }
1372 ast_str_append(&str, 0, "->");
1374 }
1375 }
1376 }
1377
1378 snprintf(src_buffer, sizeof(src_buffer), "%s:%u", src_codec->name, src_codec->sample_rate);
1379 snprintf(dst_buffer, sizeof(dst_buffer), "%s:%u", dst_codec->name, dst_codec->sample_rate);
1380 ast_cli(a->fd, "\t%-16.16s To %-16.16s: %-60.60s\n",
1381 src_buffer, dst_buffer, ast_str_buffer(str));
1383 ao2_ref(dst_codec, -1);
1384 }
1386 ao2_ref(src_codec, -1);
1387 return CLI_SUCCESS;
1388}
#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 1205 of file translate.c.

1206{
1207 int x, y, i, k, compCost;
1208 int longest = 7; /* slin192 */
1209 int max_codec_index = 0, curlen = 0;
1210 struct ast_str *out = ast_str_create(1024);
1211 struct ast_codec *codec;
1212
1213 /* Get the length of the longest (usable?) codec name,
1214 so we know how wide the left side should be */
1215 for (i = 1; (codec = ast_codec_get_by_id(i)); ao2_ref(codec, -1), ++i) {
1216 ++max_codec_index;
1217 if (codec->type != AST_MEDIA_TYPE_AUDIO) {
1218 continue;
1219 }
1220 curlen = strlen(codec->name);
1221 if (curlen > longest) {
1222 longest = curlen;
1223 }
1224 }
1225
1227 ast_cli(a->fd, " Translation times between formats (in microseconds) for one second of data\n");
1228 ast_cli(a->fd, " Source Format (Rows) Destination Format (Columns)\n\n");
1229
1230 for (i = 0; i <= max_codec_index; i++) {
1231 struct ast_codec *row = i ? ast_codec_get_by_id(i) : NULL;
1232
1233 x = -1;
1234 if ((i > 0) && (row->type != AST_MEDIA_TYPE_AUDIO)) {
1235 ao2_ref(row, -1);
1236 continue;
1237 }
1238
1239 if ((i > 0) && (x = codec2index(row)) == -1) {
1240 ao2_ref(row, -1);
1241 continue;
1242 }
1243
1244 ast_str_set(&out, 0, " ");
1245 for (k = 0; k <= max_codec_index; k++) {
1246 int adjust = 0;
1247 struct ast_codec *col = k ? ast_codec_get_by_id(k) : NULL;
1248
1249 y = -1;
1250 if ((k > 0) && (col->type != AST_MEDIA_TYPE_AUDIO)) {
1251 ao2_ref(col, -1);
1252 continue;
1253 }
1254
1255 if ((k > 0) && (y = codec2index(col)) == -1) {
1256 ao2_ref(col, -1);
1257 continue;
1258 }
1259
1260 if (k > 0) {
1261 curlen = strlen(col->name);
1262 if (!strcmp(col->name, "slin") ||
1263 !strcmp(col->name, "speex") ||
1264 !strcmp(col->name, "silk")) {
1265 adjust = log10(col->sample_rate / 1000) + 1;
1266 curlen = curlen + adjust;
1267 }
1268 }
1269
1270 if (curlen < 5) {
1271 curlen = 5;
1272 }
1273
1274 if (x >= 0 && y >= 0 && matrix_get(x, y)->step) {
1275 /* Actual codec output */
1276 if (a->argv[3] && !strcasecmp(a->argv[3], "comp")) {
1277 compCost = matrix_get(x, y)->comp_cost;
1278 if (compCost == 0 || compCost == 999999) {
1279 ast_str_append(&out, 0, "%*s", curlen + 1, "-");
1280 } else {
1281 ast_str_append(&out, 0, "%*u", curlen + 1, compCost);
1282 }
1283 } else {
1284 ast_str_append(&out, 0, "%*u", curlen + 1, (matrix_get(x, y)->table_cost / 100));
1285 }
1286 } else if (i == 0 && k > 0) {
1287 /* Top row - use a dynamic size */
1288 if (!strcmp(col->name, "slin") ||
1289 !strcmp(col->name, "speex") ||
1290 !strcmp(col->name, "silk")) {
1291 ast_str_append(&out, 0, "%*s%u", curlen - adjust + 1,
1292 col->name, col->sample_rate / 1000);
1293 } else {
1294 ast_str_append(&out, 0, "%*s", curlen + 1, col->name);
1295 }
1296 } else if (k == 0 && i > 0) {
1297 /* Left column - use a static size. */
1298 if (!strcmp(row->name, "slin") ||
1299 !strcmp(row->name, "speex") ||
1300 !strcmp(row->name, "silk")) {
1301 int adjust_row = log10(row->sample_rate / 1000) + 1;
1302 ast_str_append(&out, 0, "%*s%u", longest - adjust_row,
1303 row->name, row->sample_rate / 1000);
1304 } else {
1305 ast_str_append(&out, 0, "%*s", longest, row->name);
1306 }
1307 } else if (x >= 0 && y >= 0) {
1308 /* Codec not supported */
1309 ast_str_append(&out, 0, "%*s", curlen + 1, "-");
1310 } else {
1311 /* Upper left hand corner */
1312 ast_str_append(&out, 0, "%*s", longest, "");
1313 }
1314 ao2_cleanup(col);
1315 }
1316 ast_str_append(&out, 0, "\n");
1317 ast_cli(a->fd, "%s", ast_str_buffer(out));
1318 ao2_cleanup(row);
1319 }
1320 ast_free(out);
1322 return CLI_SUCCESS;
1323}
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
uint32_t comp_cost
Definition translate.c:119

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

229{
230 struct ast_codec *codec;
231
232 if (index >= cur_max_index) {
233 return 0;
234 }
236 codec = ast_codec_get_by_id(__indextable[index]);
238
239 return codec;
240}

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

Referenced by matrix_rebuild().

◆ lcg_rand()

static uint32_t lcg_rand ( void  )
static

Definition at line 62 of file translate.c.

63{
64 lcg_state = lcg_state * 1664525u + 1013904223u;
65 return lcg_state;
66}
static uint32_t lcg_state
Definition translate.c:61

References lcg_state.

Referenced by generate_samples().

◆ matrix_clear()

static void matrix_clear ( void  )
static

Definition at line 326 of file translate.c.

327{
328 int x;
329 for (x = 0; x < index_size; x++) {
330 memset(__matrix[x], '\0', sizeof(struct translator_path) * (index_size));
331 }
332}
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:134

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

1041{
1042 struct ast_translator *t;
1043 int newtablecost;
1044 int x; /* source format index */
1045 int y; /* intermediate format index */
1046 int z; /* destination format index */
1047
1048 ast_debug(1, "Resetting translation matrix\n");
1049
1050 matrix_clear();
1051
1052 /* first, compute all direct costs */
1054 if (!t->active) {
1055 continue;
1056 }
1057
1058 x = t->src_fmt_index;
1059 z = t->dst_fmt_index;
1060
1061 if (samples) {
1062 generate_computational_cost(t, samples);
1063 }
1064
1065 /* This new translator is the best choice if any of the below are true.
1066 * 1. no translation path is set between x and z yet.
1067 * 2. the new table cost is less.
1068 * 3. the new computational cost is less. Computational cost is only used
1069 * to break a tie between two identical translation paths.
1070 */
1071 if (!matrix_get(x, z)->step ||
1072 (t->table_cost < matrix_get(x, z)->step->table_cost) ||
1073 (t->comp_cost < matrix_get(x, z)->step->comp_cost)) {
1074
1075 matrix_get(x, z)->step = t;
1076 matrix_get(x, z)->table_cost = t->table_cost;
1077 matrix_get(x, z)->comp_cost = t->comp_cost;
1078 }
1079 }
1080
1081 /*
1082 * For each triple x, y, z of distinct formats, check if there is
1083 * a path from x to z through y which is cheaper than what is
1084 * currently known, and in case, update the matrix.
1085 * Repeat until the matrix is stable.
1086 */
1087 for (;;) {
1088 int changed = 0;
1089 for (x = 0; x < cur_max_index; x++) { /* source format */
1090 for (y = 0; y < cur_max_index; y++) { /* intermediate format */
1091 if (x == y) { /* skip ourselves */
1092 continue;
1093 }
1094 for (z = 0; z < cur_max_index; z++) { /* dst format */
1095 if ((z == x || z == y) || /* skip null conversions */
1096 !matrix_get(x, y)->step || /* no path from x to y */
1097 !matrix_get(y, z)->step) { /* no path from y to z */
1098 continue;
1099 }
1100
1101 /* calculate table cost from x->y->z */
1102 newtablecost = matrix_get(x, y)->table_cost + matrix_get(y, z)->table_cost;
1103
1104 /* if no step already exists between x and z OR the new cost of using the intermediate
1105 * step is cheaper, use this step. */
1106 if (!matrix_get(x, z)->step || (newtablecost < matrix_get(x, z)->table_cost)) {
1107 matrix_get(x, z)->step = matrix_get(x, y)->step;
1108 matrix_get(x, z)->table_cost = newtablecost;
1109 matrix_get(x, z)->multistep = 1;
1110 changed++;
1111
1112 if (DEBUG_ATLEAST(10)) {
1113 struct ast_codec *x_codec = index2codec(x);
1114 struct ast_codec *y_codec = index2codec(y);
1115 struct ast_codec *z_codec = index2codec(z);
1116
1118 "Discovered %u cost path from %s to %s, via %s\n",
1119 matrix_get(x, z)->table_cost, x_codec->name,
1120 y_codec->name, z_codec->name);
1121
1122 ao2_ref(x_codec, -1);
1123 ao2_ref(y_codec, -1);
1124 ao2_ref(z_codec, -1);
1125 }
1126 }
1127 }
1128 }
1129 }
1130 if (!changed) {
1131 break;
1132 }
1133 }
1134}
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
#define AST_RWLIST_TRAVERSE
static void matrix_clear(void)
Definition translate.c:326
static struct ast_codec * index2codec(int index)
Definition translate.c:228

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(), handle_cli_translate_sampletype(), and matrix_resize().

◆ matrix_resize()

static int matrix_resize ( int  init)
static

Definition at line 252 of file translate.c.

253{
254 struct translator_path **tmp_matrix = NULL;
255 unsigned int *tmp_table = NULL;
256 int old_index;
257 int x;
258
261
262 old_index = index_size;
263 if (init) {
265 } else {
267 }
268
269 /* make new 2d array of translator_path structures */
270 if (!(tmp_matrix = ast_calloc(1, sizeof(struct translator_path *) * (index_size)))) {
271 goto resize_cleanup;
272 }
273
274 for (x = 0; x < index_size; x++) {
275 if (!(tmp_matrix[x] = ast_calloc(1, sizeof(struct translator_path) * (index_size)))) {
276 goto resize_cleanup;
277 }
278 }
279
280 /* make new index table */
281 if (!(tmp_table = ast_calloc(1, sizeof(unsigned int) * index_size))) {
282 goto resize_cleanup;
283 }
284
285 /* if everything went well this far, free the old and use the new */
286 if (!init) {
287 for (x = 0; x < old_index; x++) {
288 ast_free(__matrix[x]);
289 }
291
292 memcpy(tmp_table, __indextable, sizeof(unsigned int) * old_index);
294 }
295
296 /* now copy them over */
297 __matrix = tmp_matrix;
298 __indextable = tmp_table;
299
303
304 return 0;
305
306resize_cleanup:
309 if (tmp_matrix) {
310 for (x = 0; x < index_size; x++) {
311 ast_free(tmp_matrix[x]);
312 }
313 ast_free(tmp_matrix);
314 }
315 ast_free(tmp_table);
316
317 return -1;
318}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define INIT_INDEX
Definition translate.c:147
#define GROW_INDEX
Definition translate.c:149

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

370{
371 struct ast_trans_pvt *pvt;
372 int len;
373 char *ofs;
374
375 /*
376 * compute the required size adding private descriptor,
377 * buffer, AST_FRIENDLY_OFFSET.
378 */
379 len = sizeof(*pvt) + t->desc_size;
380 if (t->buf_size)
382 pvt = ast_calloc(1, len);
383 if (!pvt) {
384 return NULL;
385 }
386 pvt->t = t;
387 ofs = (char *)(pvt + 1); /* pointer to data space */
388 if (t->desc_size) { /* first comes the descriptor */
389 pvt->pvt = ofs;
390 ofs += t->desc_size;
391 }
392 if (t->buf_size) {/* finally buffer and header */
393 pvt->outbuf.c = ofs + AST_FRIENDLY_OFFSET;
394 }
395 /*
396 * If the format has an attribute module, explicit_dst includes the (joined)
397 * result of the SDP negotiation. For example with the Opus Codec, the format
398 * knows whether both parties want to do forward-error correction (FEC).
399 */
400 pvt->explicit_dst = ao2_bump(explicit_dst);
401
402 ast_module_ref(t->module);
403
404 /* call local init routine, if present */
405 if (t->newpvt && t->newpvt(pvt)) {
406 ast_free(pvt);
407 ast_module_unref(t->module);
408 return NULL;
409 }
410
411 /* Setup normal static translation frame. */
412 pvt->f.frametype = AST_FRAME_VOICE;
413 pvt->f.mallocd = 0;
414 pvt->f.offset = AST_FRIENDLY_OFFSET;
415 pvt->f.src = pvt->t->name;
416 pvt->f.data.ptr = pvt->outbuf.c;
417
418 /*
419 * If the translator has not provided a format
420 * A) use the joined one,
421 * B) use the cached one, or
422 * C) create one.
423 */
424 if (!pvt->f.subclass.format) {
425 pvt->f.subclass.format = ao2_bump(pvt->explicit_dst);
426
427 if (!pvt->f.subclass.format && !ast_strlen_zero(pvt->t->format)) {
428 pvt->f.subclass.format = ast_format_cache_get(pvt->t->format);
429 }
430
431 if (!pvt->f.subclass.format) {
432 struct ast_codec *codec = ast_codec_get(t->dst_codec.name,
434 if (!codec) {
435 ast_log(LOG_ERROR, "Unable to get destination codec\n");
436 destroy(pvt);
437 return NULL;
438 }
439 pvt->f.subclass.format = ast_format_create(codec);
440 ao2_ref(codec, -1);
441 }
442
443 if (!pvt->f.subclass.format) {
444 ast_log(LOG_ERROR, "Unable to create format\n");
445 destroy(pvt);
446 return NULL;
447 }
448 }
449
450 return pvt;
451}
#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.
#define ast_module_ref(mod)
Hold a reference to the module.
Definition module.h:457
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_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(), build_slin_to_src_path(), and generate_computational_cost().

◆ translate_shutdown()

static void translate_shutdown ( void  )
static

Definition at line 1932 of file translate.c.

1933{
1934 int x;
1936
1938 for (x = 0; x < index_size; x++) {
1939 ast_free(__matrix[x]);
1940 }
1942 __matrix = NULL;
1947}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
#define ast_rwlock_destroy(rwlock)
Definition lock.h:240

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 141 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 134 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" ,},
{ .handler = handle_cli_translate_sampletype , .summary = "Get/set codec matrix sample type" ,},
}
static char * handle_cli_translate_sampletype(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition translate.c:1447
static char * handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition translate.c:1390

Definition at line 1505 of file translate.c.

1505 {
1506 AST_CLI_DEFINE(handle_cli_core_show_translation, "Display translation matrix"),
1507 AST_CLI_DEFINE(handle_cli_translate_sampletype, "Get/set codec matrix sample type"),
1508};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

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

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

◆ current_sample_type

enum sample_type current_sample_type = SAMPLE_TYPE_CODEC
static

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

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

◆ lcg_state

uint32_t lcg_state = 0xdeadbeef
static

Simple LCG state for reproducible pseudo-random noise

Definition at line 61 of file translate.c.

Referenced by lcg_rand().

◆ tablelock

ast_rwlock_t tablelock
static

protects the __indextable for resizing

Definition at line 144 of file translate.c.

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

◆ translators