33#include <sys/resource.h>
54#define MAX_RECALC 1000
198 unsigned int *tmp_table =
NULL;
230 for (x = 0; x < old_index; x++) {
235 memcpy(tmp_table,
__indextable,
sizeof(
unsigned int) * old_index);
330 ofs = (
char *)(
pvt + 1);
358 pvt->f.src =
pvt->t->name;
359 pvt->f.data.ptr =
pvt->outbuf.c;
367 if (!
pvt->f.subclass.format) {
374 if (!
pvt->f.subclass.format) {
407 if (!f->
src || strcasecmp(f->
src,
"ast_prod")) {
489 int src_index, dst_index;
494 if (src_index < 0 || dst_index < 0) {
495 ast_log(
LOG_WARNING,
"No translator path: (%s codec is not valid)\n", src_index < 0 ?
"starting" :
"ending");
501 while (src_index != dst_index) {
515 if (!(cur =
newpvt(t, explicit_dst))) {
570 struct timeval delivery;
580 for (tp = p; tp; tp = tp->
next) {
665 if (has_timing_info) {
706 ast_debug(3,
"Translator '%s' does not produce sample frames.\n", t->
name);
718 getrusage(RUSAGE_SELF, &start);
721 while (num_samples < seconds * out_rate) {
737 getrusage(RUSAGE_SELF, &
end);
739 cost = ((
end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000) +
end.ru_utime.tv_usec - start.ru_utime.tv_usec;
740 cost += ((
end.ru_stime.tv_sec - start.ru_stime.tv_sec) * 1000000) +
end.ru_stime.tv_usec - start.ru_stime.tv_usec;
771 int src_rate =
src->sample_rate;
784 src_ll = !strcmp(
src->name,
"slin");
785 dst_ll = !strcmp(dst->
name,
"slin");
787 if (dst_ll && (src_rate == dst_rate)) {
789 }
else if (!dst_ll && (src_rate == dst_rate)) {
791 }
else if (dst_ll && (src_rate < dst_rate)) {
793 }
else if (!dst_ll && (src_rate < dst_rate)) {
795 }
else if (dst_ll && (src_rate > dst_rate)) {
797 }
else if (!dst_ll && (src_rate > dst_rate)) {
803 if (dst_ll && (src_rate == dst_rate)) {
805 }
else if (!dst_ll && (src_rate == dst_rate)) {
807 }
else if (dst_ll && (src_rate < dst_rate)) {
809 }
else if (!dst_ll && (src_rate < dst_rate)) {
811 }
else if (dst_ll && (src_rate > dst_rate)) {
813 }
else if (!dst_ll && (src_rate > dst_rate)) {
833 ast_debug(1,
"Resetting translation matrix\n");
880 if ((z == x || z == y) ||
903 "Discovered %u cost path from %s to %s, via %s\n",
950 int wordlen = strlen(
word);
959 if (!strncasecmp(
word, codec->
name, wordlen)) {
973 int time =
a->argv[4] ? atoi(
a->argv[4]) : 1;
976 ast_cli(
a->fd,
" Recalc must be greater than 0. Defaulting to 1.\n");
984 ast_cli(
a->fd,
" Recalculating Codec Translation (number of sample seconds: %d)\n\n", time);
992 int x, y, i, k, compCost;
994 int max_codec_index = 0, curlen = 0;
1005 curlen = strlen(codec->
name);
1006 if (curlen > longest) {
1012 ast_cli(
a->fd,
" Translation times between formats (in microseconds) for one second of data\n");
1013 ast_cli(
a->fd,
" Source Format (Rows) Destination Format (Columns)\n\n");
1015 for (i = 0; i <= max_codec_index; i++) {
1030 for (k = 0; k <= max_codec_index; k++) {
1046 curlen = strlen(col->
name);
1047 if (!strcmp(col->
name,
"slin") ||
1048 !strcmp(col->
name,
"speex") ||
1049 !strcmp(col->
name,
"silk")) {
1051 curlen = curlen + adjust;
1059 if (x >= 0 && y >= 0 &&
matrix_get(x, y)->step) {
1061 if (
a->argv[3] && !strcasecmp(
a->argv[3],
"comp")) {
1063 if (compCost == 0 || compCost == 999999) {
1071 }
else if (i == 0 && k > 0) {
1073 if (!strcmp(col->
name,
"slin") ||
1074 !strcmp(col->
name,
"speex") ||
1075 !strcmp(col->
name,
"silk")) {
1081 }
else if (k == 0 && i > 0) {
1083 if (!strcmp(row->
name,
"slin") ||
1084 !strcmp(row->
name,
"speex") ||
1085 !strcmp(row->
name,
"silk")) {
1086 int adjust_row = log10(row->
sample_rate / 1000) + 1;
1092 }
else if (x >= 0 && y >= 0) {
1119 ast_cli(
a->fd,
"Source codec \"%s\" is not found.\n", codec_name);
1124 ast_cli(
a->fd,
"--- Translation paths SRC Codec \"%s\" sample rate %u ---\n",
1129 char src_buffer[64];
1130 char dst_buffer[64];
1133 if (src_codec == dst_codec ||
1142 if (src < 0 || dst < 0) {
1149 while (src != dst) {
1163 snprintf(src_buffer,
sizeof(src_buffer),
"%s:%u", src_codec->
name, src_codec->
sample_rate);
1164 snprintf(dst_buffer,
sizeof(dst_buffer),
"%s:%u", dst_codec->
name, dst_codec->
sample_rate);
1165 ast_cli(
a->fd,
"\t%-16.16s To %-16.16s: %-60.60s\n",
1177 static const char *
const option[] = {
"recalc",
"paths",
"comp",
NULL };
1181 e->
command =
"core show translation";
1183 "Usage: 'core show translation' can be used in three ways.\n"
1184 " 1. 'core show translation [recalc [<recalc seconds>]\n"
1185 " Displays known codec translators and the cost associated\n"
1186 " with each conversion. If the argument 'recalc' is supplied along\n"
1187 " with optional number of seconds to test a new test will be performed\n"
1188 " as the chart is being displayed.\n"
1189 " 2. 'core show translation paths [codec [sample_rate]]'\n"
1190 " This will display all the translation paths associated with a codec.\n"
1191 " If a codec has multiple sample rates, the sample rate must be\n"
1192 " provided as well.\n"
1193 " 3. 'core show translation comp [<recalc seconds>]'\n"
1194 " Displays known codec translators and the cost associated\n"
1195 " with each conversion. If the argument 'recalc' is supplied along\n"
1196 " with optional number of seconds to test a new test will be performed\n"
1197 " as the chart is being displayed. The resulting numbers in the table\n"
1198 " give the actual computational costs in microseconds.\n";
1204 if (
a->pos == 4 && !strcasecmp(
a->argv[3], option[1])) {
1214 if (
a->argv[3] && !strcasecmp(
a->argv[3], option[1]) &&
a->argc == 5) {
1216 }
else if (
a->argv[3] && !strcasecmp(
a->argv[3], option[1]) &&
a->argc == 6) {
1219 ast_cli(
a->fd,
"Invalid sample rate: %s.\n",
a->argv[5]);
1223 }
else if (
a->argv[3] && (!strcasecmp(
a->argv[3], option[0]) || !strcasecmp(
a->argv[3], option[2]))) {
1225 }
else if (
a->argc > 3) {
1259 ast_log(
LOG_WARNING,
"Translator matrix can not represent any more translators. Out of resources.\n");
1277 "Please set table_cost variable on translator.\n", t->
name);
1305 struct _test_align {
void *
a, *
b; } p;
1306 int align = (
char *)&p.b - (
char *)&p.a;
1317 ast_verb(5,
"Registered translator '%s' from codec %s to %s, table cost, %d, computational cost %d\n",
1360 ast_verb(5,
"Unregistered translator '%s' from codec %s to %s\n",
1375 return (u ? 0 : -1);
1395#define format_sample_rate_absdiff(fmt1, fmt2) ({ \
1396 unsigned int rate1 = ast_format_get_sample_rate(fmt1); \
1397 unsigned int rate2 = ast_format_get_sample_rate(fmt2); \
1398 (rate1 > rate2 ? rate1 - rate2 : rate2 - rate1); \
1407 unsigned int besttablecost = INT_MAX;
1408 unsigned int beststeps = INT_MAX;
1419 ast_log(
LOG_ERROR,
"Cannot determine best translation path since one capability supports no formats\n");
1470 if (x < 0 || y < 0) {
1476 if (
matrix_get(x, y)->table_cost < besttablecost
1477 ||
matrix_get(x, y)->multistep < beststeps) {
1483 }
else if (
matrix_get(x, y)->table_cost == besttablecost
1484 &&
matrix_get(x, y)->multistep == beststeps) {
1489 if (gap_current < gap_selected) {
1492 }
else if (gap_current == gap_selected) {
1493 int src_quality, best_quality;
1494 struct ast_codec *src_codec, *best_codec;
1498 src_quality = src_codec->
quality;
1499 best_quality = best_codec->
quality;
1505 if (src_quality > best_quality) {
1513 ast_debug(1,
"Completely ambiguous tie between formats %s and %s (quality %d): sticking with %s, but this is arbitrary\n",
1538 unsigned int res = -1;
1543 if (src < 0 || dest < 0) {
1544 ast_log(
LOG_WARNING,
"No translator path: (%s codec is not valid)\n", src < 0 ?
"starting" :
"ending");
1574 int index, src_index;
1596 if (src_index < 0 || index < 0) {
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
int ast_shutting_down(void)
#define ast_strdup(str)
A wrapper for strdup()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
General Asterisk PBX channel definitions.
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
void ast_cli(int fd, const char *fmt,...)
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
ast_media_type
Types of media.
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.
struct ast_codec * ast_codec_get_by_id(int id)
Retrieve a codec given the unique identifier.
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Asterisk internal frame definitions.
@ AST_FRFLAG_HAS_TIMING_INFO
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_frdup(fr)
Copies a frame.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
struct ast_frame ast_null_frame
#define DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
A set of macros to manage forward-linked lists.
#define AST_RWLIST_REMOVE_CURRENT
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_RWLIST_TRAVERSE_SAFE_END
#define AST_RWLIST_TRAVERSE
#define AST_RWLIST_INSERT_HEAD
#define AST_RWLIST_INSERT_BEFORE_CURRENT
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Asterisk locking-related definitions:
#define ast_rwlock_wrlock(a)
#define ast_rwlock_rdlock(a)
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
#define ast_rwlock_destroy(rwlock)
#define ast_rwlock_unlock(a)
Asterisk module definitions.
#define ast_module_unref(mod)
Release a reference to the module.
#define ast_module_ref(mod)
Hold a reference to the module.
#define ast_opt_generic_plc
Scheduler Routines (derived from cheops)
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_alloca(init_len)
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
descriptor for a cli entry.
Represents a media codec within Asterisk.
unsigned int sample_rate
Sample rate (number of samples carried in a second)
enum ast_media_type type
Type of media this codec contains.
unsigned int quality
Format quality, on scale from 0 to 150 (100 is ulaw, the reference). This allows better format to be ...
const char * name
Name for this codec.
unsigned int id
Internal unique identifier for this codec, set at registration time (starts at 1)
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
Structure for rwlock and tracking information.
Support for dynamic strings.
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
struct ast_trans_pvt * next
struct ast_translator * t
struct ast_format * explicit_dst
int datalen
actual space used in outbuf
union ast_trans_pvt::@287 outbuf
Descriptor of a translator.
void(* destroy)(struct ast_trans_pvt *pvt)
struct ast_frame *(* sample)(void)
void(* feedback)(struct ast_trans_pvt *pvt, struct ast_frame *feedback)
int buffer_samples
size of outbuf, in samples. Leave it 0 if you want the framein callback deal with the frame....
int buf_size
size of outbuf, in bytes. Mandatory. The wrapper code will also allocate an AST_FRIENDLY_OFFSET space...
struct ast_translator::@286 list
int(* framein)(struct ast_trans_pvt *pvt, struct ast_frame *in)
struct ast_codec src_codec
struct ast_module * module
struct ast_frame *(* frameout)(struct ast_trans_pvt *pvt)
int(* newpvt)(struct ast_trans_pvt *)
struct ast_codec dst_codec
struct ast_translator * step
Handy terminal functions for vt* terms.
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
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 ...
int ast_tveq(struct timeval _a, struct timeval _b)
Returns true if the two struct timeval arguments are equal.
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
static char * handle_show_translation_table(struct ast_cli_args *a)
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'.
#define format_sample_rate_absdiff(fmt1, fmt2)
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)
void ast_translator_activate(struct ast_translator *t)
Activate a previously deactivated translator.
static void handle_cli_recalc(struct ast_cli_args *a)
static int add_codec2index(struct ast_codec *codec)
static int codec_to_index(unsigned int id)
static struct ast_frame * default_frameout(struct ast_trans_pvt *pvt)
void ast_translator_free_path(struct ast_trans_pvt *p)
Frees a translator path Frees the given translator path structure.
static ast_rwlock_t tablelock
static void matrix_rebuild(int samples)
rebuild a translation matrix.
int ast_unregister_translator(struct ast_translator *t)
unregister codec translator
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,...
static void matrix_clear(void)
void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result)
Find available formats.
static int matrix_resize(int init)
void ast_translator_deactivate(struct ast_translator *t)
Deactivate a translator.
static unsigned int * __indextable
table for converting index to format values.
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.
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.
static struct ast_trans_pvt * newpvt(struct ast_translator *t, struct ast_format *explicit_dst)
Allocate the descriptor, required outbuf space, and possibly desc.
struct ast_frame * ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume)
do the actual translation
static struct translator_path ** __matrix
a matrix that, for any pair of supported formats, indicates the total cost of translation and the fir...
static int codec2index(struct ast_codec *codec)
static struct translator_path * matrix_get(unsigned int x, unsigned int y)
static void translate_shutdown(void)
static void generate_computational_cost(struct ast_translator *t, int seconds)
int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
register codec translator
static void codec_append_name(const struct ast_codec *codec, struct ast_str **buf)
static char * handle_show_translation_path(struct ast_cli_args *a, const char *codec_name, unsigned int sample_rate)
static struct ast_cli_entry cli_translate[]
static void destroy(struct ast_trans_pvt *pvt)
static struct ast_frame * generate_interpolated_slin(struct ast_trans_pvt *p, struct ast_frame *f)
static int generate_table_cost(struct ast_codec *src, struct ast_codec *dst)
static struct ast_codec * index2codec(int index)
static char * complete_trans_path_choice(const char *word)
static int framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
framein wrapper, deals with bound checks.
static int format2index(struct ast_format *format)
static char * handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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.
int ast_translate_init(void)
Initialize the translation matrix and index to format conversion table.
Support for translation of data formats. translate.c.
@ AST_TRANS_COST_LY_LY_DOWNSAMP
@ AST_TRANS_COST_LL_LL_DOWNSAMP
@ AST_TRANS_COST_LY_LY_ORIGSAMP
@ AST_TRANS_COST_LL_LL_UPSAMP
@ AST_TRANS_COST_LY_LL_ORIGSAMP
@ AST_TRANS_COST_LL_UNKNOWN
@ AST_TRANS_COST_LY_LL_DOWNSAMP
@ AST_TRANS_COST_LL_LY_DOWNSAMP
@ AST_TRANS_COST_LL_LY_ORIGSAMP
@ AST_TRANS_COST_LY_UNKNOWN
@ AST_TRANS_COST_LL_LY_UPSAMP
@ AST_TRANS_COST_LY_LY_UPSAMP
@ AST_TRANS_COST_LY_LL_UPSAMP
@ AST_TRANS_COST_LL_LL_ORIGSAMP
#define ast_test_flag(p, flag)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_set2_flag(p, value, flag)
#define ast_clear_flag(p, flag)
#define ast_copy_flags(dest, src, flagz)