33#include <sys/resource.h>
79 memset(
buf, 0, samples *
sizeof(int16_t));
82 for (i = 0; i < samples; i++) {
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);
95 sig *= 0.5 * (1.0 + sin(2.0 *
M_PI * 4.0 * t));
96 buf[i] = (int16_t)(sig * 16000.0);
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);
111#define MAX_RECALC 1000
255 unsigned int *tmp_table =
NULL;
287 for (x = 0; x < old_index; x++) {
292 memcpy(tmp_table,
__indextable,
sizeof(
unsigned int) * old_index);
387 ofs = (
char *)(
pvt + 1);
415 pvt->f.src =
pvt->t->name;
416 pvt->f.data.ptr =
pvt->outbuf.c;
424 if (!
pvt->f.subclass.format) {
431 if (!
pvt->f.subclass.format) {
464 if (!f->
src || strcasecmp(f->
src,
"ast_prod")) {
546 int src_index, dst_index;
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");
558 while (src_index != dst_index) {
572 if (!(cur =
newpvt(t, explicit_dst))) {
627 struct timeval delivery;
637 for (tp = p; tp; tp = tp->
next) {
722 if (has_timing_info) {
740#define PRE_ENCODE_POOL_MAX 200
755 int slin_index, dst_index;
769 if (slin_index < 0) {
774 if (dst_index < 0 || slin_index == dst_index) {
778 while (slin_index != dst_index) {
821 int pre_pool_count = 0;
822 int pre_pool_idx = 0;
823 int use_pre_pool = 0;
831 ast_debug(3,
"Translator '%s' does not produce sample frames.\n", t->
name);
853 int16_t slin_buf[80];
867 slin_f.datalen =
sizeof(slin_buf);
869 slin_f.data.ptr = slin_buf;
870 slin_f.src = __PRETTY_FUNCTION__;
887 for (pp = pre_path; pp; pp = pp->
next) {
905 pre_pool[pre_pool_count++] =
out;
908 use_pre_pool = (pre_pool_count > 0);
914 getrusage(RUSAGE_SELF, &start);
917 while (num_samples < seconds * out_rate) {
922 framein(pvt, pre_pool[pre_pool_idx % pre_pool_count]);
943 getrusage(RUSAGE_SELF, &
end);
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;
959 for (i = 0; i < pre_pool_count; i++) {
986 int src_rate =
src->sample_rate;
999 src_ll = !strcmp(
src->name,
"slin");
1000 dst_ll = !strcmp(dst->
name,
"slin");
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)) {
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)) {
1048 ast_debug(1,
"Resetting translation matrix\n");
1095 if ((z == x || z == y) ||
1118 "Discovered %u cost path from %s to %s, via %s\n",
1165 int wordlen = strlen(
word);
1174 if (!strncasecmp(
word, codec->
name, wordlen)) {
1188 int time =
a->argv[4] ? atoi(
a->argv[4]) : 1;
1191 ast_cli(
a->fd,
" Recalc must be greater than 0. Defaulting to 1.\n");
1199 ast_cli(
a->fd,
" Recalculating Codec Translation (number of sample seconds: %d)\n\n", time);
1207 int x, y, i, k, compCost;
1209 int max_codec_index = 0, curlen = 0;
1220 curlen = strlen(codec->
name);
1221 if (curlen > longest) {
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");
1230 for (i = 0; i <= max_codec_index; i++) {
1245 for (k = 0; k <= max_codec_index; k++) {
1261 curlen = strlen(col->
name);
1262 if (!strcmp(col->
name,
"slin") ||
1263 !strcmp(col->
name,
"speex") ||
1264 !strcmp(col->
name,
"silk")) {
1266 curlen = curlen + adjust;
1274 if (x >= 0 && y >= 0 &&
matrix_get(x, y)->step) {
1276 if (
a->argv[3] && !strcasecmp(
a->argv[3],
"comp")) {
1278 if (compCost == 0 || compCost == 999999) {
1286 }
else if (i == 0 && k > 0) {
1288 if (!strcmp(col->
name,
"slin") ||
1289 !strcmp(col->
name,
"speex") ||
1290 !strcmp(col->
name,
"silk")) {
1296 }
else if (k == 0 && i > 0) {
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;
1307 }
else if (x >= 0 && y >= 0) {
1334 ast_cli(
a->fd,
"Source codec \"%s\" is not found.\n", codec_name);
1339 ast_cli(
a->fd,
"--- Translation paths SRC Codec \"%s\" sample rate %u ---\n",
1344 char src_buffer[64];
1345 char dst_buffer[64];
1348 if (src_codec == dst_codec ||
1357 if (src < 0 || dst < 0) {
1364 while (src != dst) {
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",
1392 static const char *
const option[] = {
"recalc",
"paths",
"comp",
NULL };
1396 e->
command =
"core show translation";
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";
1419 if (
a->pos == 4 && !strcasecmp(
a->argv[3], option[1])) {
1429 if (
a->argv[3] && !strcasecmp(
a->argv[3], option[1]) &&
a->argc == 5) {
1431 }
else if (
a->argv[3] && !strcasecmp(
a->argv[3], option[1]) &&
a->argc == 6) {
1434 ast_cli(
a->fd,
"Invalid sample rate: %s.\n",
a->argv[5]);
1438 }
else if (
a->argv[3] && (!strcasecmp(
a->argv[3], option[0]) || !strcasecmp(
a->argv[3], option[2]))) {
1440 }
else if (
a->argc > 3) {
1450 static const char *
const types[] = {
"codec",
"sine",
"silence",
"noise",
"speech",
NULL };
1454 e->
command =
"translate sampletype";
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";
1471 const char *names[] = {
"codec",
"sine",
"silence",
"noise",
"speech" };
1472 ast_cli(
a->fd,
"Current translate sample type: %s\n",
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")) {
1491 ast_cli(
a->fd,
"Unknown sample type '%s'. Use: codec, sine, silence, noise, speech\n",
1497 ast_cli(
a->fd,
"Sample type set to '%s'. Rebuilding codec matrix...\n",
a->argv[2]);
1533 ast_log(
LOG_WARNING,
"Translator matrix can not represent any more translators. Out of resources.\n");
1551 "Please set table_cost variable on translator.\n", t->
name);
1579 struct _test_align {
void *
a, *
b; } p;
1580 int align = (
char *)&p.b - (
char *)&p.a;
1591 ast_verb(5,
"Registered translator '%s' from codec %s to %s, table cost, %d, computational cost %d\n",
1634 ast_verb(5,
"Unregistered translator '%s' from codec %s to %s\n",
1649 return (u ? 0 : -1);
1669#define format_sample_rate_absdiff(fmt1, fmt2) ({ \
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); \
1681 unsigned int besttablecost = INT_MAX;
1682 unsigned int beststeps = INT_MAX;
1693 ast_log(
LOG_ERROR,
"Cannot determine best translation path since one capability supports no formats\n");
1744 if (x < 0 || y < 0) {
1750 if (
matrix_get(x, y)->table_cost < besttablecost
1751 ||
matrix_get(x, y)->multistep < beststeps) {
1757 }
else if (
matrix_get(x, y)->table_cost == besttablecost
1758 &&
matrix_get(x, y)->multistep == beststeps) {
1763 if (gap_current < gap_selected) {
1766 }
else if (gap_current == gap_selected) {
1767 int src_quality, best_quality;
1768 struct ast_codec *src_codec, *best_codec;
1772 src_quality = src_codec->
quality;
1773 best_quality = best_codec->
quality;
1779 if (src_quality > best_quality) {
1787 ast_debug(1,
"Completely ambiguous tie between formats %s and %s (quality %d): sticking with %s, but this is arbitrary\n",
1812 unsigned int res = -1;
1817 if (src < 0 || dest < 0) {
1818 ast_log(
LOG_WARNING,
"No translator path: (%s codec is not valid)\n", src < 0 ?
"starting" :
"ending");
1848 int index, src_index;
1870 if (src_index < 0 || index < 0) {
void ast_cli_unregister_multiple(void)
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 ast_malloc(len)
A wrapper for malloc()
#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.
#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.
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_frdup(fr)
Copies a frame.
@ AST_FRFLAG_HAS_TIMING_INFO
#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
static void cleanup(void)
Clean up any old apps that we don't need any more.
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.
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.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
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
enum ast_frame_type frametype
union ast_frame::@235 data
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
union ast_trans_pvt::@304 outbuf
struct ast_format * explicit_dst
int datalen
actual space used in outbuf
Descriptor of a translator.
struct ast_module *int active
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...
int(* framein)(struct ast_trans_pvt *pvt, struct ast_frame *in)
struct ast_codec src_codec
struct ast_translator::@303 list
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 uint32_t lcg_rand(void)
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 * build_slin_to_src_path(const struct ast_translator *t)
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
#define PRE_ENCODE_POOL_MAX
static enum sample_type current_sample_type
static struct translator_path ** __matrix
a matrix that, for any pair of supported formats, indicates the total cost of translation and the fir...
static void generate_samples(int16_t *buf, int samples, int offset)
Fill a buffer with samples of the selected type.
static char * handle_cli_translate_sampletype(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 uint32_t lcg_state
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)