mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 20:04:50 +00:00
Allow translation table to be recalculated, including with higher resolution
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2996 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
135
translate.c
135
translate.c
@@ -29,6 +29,8 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAX_RECALC 200 /* max sample recalc */
|
||||
|
||||
/* This could all be done more efficiently *IF* we chained packets together
|
||||
by default, but it would also complicate virtually every application. */
|
||||
|
||||
@@ -219,7 +221,55 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void rebuild_matrix(void)
|
||||
|
||||
static void calc_cost(struct ast_translator *t,int samples)
|
||||
{
|
||||
int sofar=0;
|
||||
struct ast_translator_pvt *pvt;
|
||||
struct ast_frame *f, *out;
|
||||
struct timeval start, finish;
|
||||
int cost;
|
||||
if(!samples)
|
||||
samples = 1;
|
||||
|
||||
/* If they don't make samples, give them a terrible score */
|
||||
if (!t->sample) {
|
||||
ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
|
||||
t->cost = 99999;
|
||||
return;
|
||||
}
|
||||
pvt = t->new();
|
||||
if (!pvt) {
|
||||
ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
|
||||
t->cost = 99999;
|
||||
return;
|
||||
}
|
||||
gettimeofday(&start, NULL);
|
||||
/* Call the encoder until we've processed one second of time */
|
||||
while(sofar < samples * 8000) {
|
||||
f = t->sample();
|
||||
if (!f) {
|
||||
ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
|
||||
t->destroy(pvt);
|
||||
t->cost = 99999;
|
||||
return;
|
||||
}
|
||||
t->framein(pvt, f);
|
||||
ast_frfree(f);
|
||||
while((out = t->frameout(pvt))) {
|
||||
sofar += out->samples;
|
||||
ast_frfree(out);
|
||||
}
|
||||
}
|
||||
gettimeofday(&finish, NULL);
|
||||
t->destroy(pvt);
|
||||
cost = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000;
|
||||
t->cost = cost / samples;
|
||||
if (!t->cost)
|
||||
t->cost = 1;
|
||||
}
|
||||
|
||||
static void rebuild_matrix(int samples)
|
||||
{
|
||||
struct ast_translator *t;
|
||||
int changed;
|
||||
@@ -230,6 +280,9 @@ static void rebuild_matrix(void)
|
||||
bzero(tr_matrix, sizeof(tr_matrix));
|
||||
t = list;
|
||||
while(t) {
|
||||
if(samples)
|
||||
calc_cost(t,samples);
|
||||
|
||||
if (!tr_matrix[t->srcfmt][t->dstfmt].step ||
|
||||
tr_matrix[t->srcfmt][t->dstfmt].cost > t->cost) {
|
||||
tr_matrix[t->srcfmt][t->dstfmt].step = t;
|
||||
@@ -267,57 +320,35 @@ static void rebuild_matrix(void)
|
||||
} while (changed);
|
||||
}
|
||||
|
||||
static void calc_cost(struct ast_translator *t)
|
||||
{
|
||||
int sofar=0;
|
||||
struct ast_translator_pvt *pvt;
|
||||
struct ast_frame *f, *out;
|
||||
struct timeval start, finish;
|
||||
int cost;
|
||||
/* If they don't make samples, give them a terrible score */
|
||||
if (!t->sample) {
|
||||
ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
|
||||
t->cost = 99999;
|
||||
return;
|
||||
}
|
||||
pvt = t->new();
|
||||
if (!pvt) {
|
||||
ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
|
||||
t->cost = 99999;
|
||||
return;
|
||||
}
|
||||
gettimeofday(&start, NULL);
|
||||
/* Call the encoder until we've processed one second of time */
|
||||
while(sofar < 8000) {
|
||||
f = t->sample();
|
||||
if (!f) {
|
||||
ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
|
||||
t->destroy(pvt);
|
||||
t->cost = 99999;
|
||||
return;
|
||||
}
|
||||
t->framein(pvt, f);
|
||||
ast_frfree(f);
|
||||
while((out = t->frameout(pvt))) {
|
||||
sofar += out->samples;
|
||||
ast_frfree(out);
|
||||
}
|
||||
}
|
||||
gettimeofday(&finish, NULL);
|
||||
t->destroy(pvt);
|
||||
cost = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000;
|
||||
t->cost = cost;
|
||||
if (!t->cost)
|
||||
t->cost = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int show_translation(int fd, int argc, char *argv[])
|
||||
{
|
||||
#define SHOW_TRANS 11
|
||||
int x,y;
|
||||
int x,y,z;
|
||||
char line[80];
|
||||
if (argc != 2)
|
||||
if (argc > 4)
|
||||
return RESULT_SHOWUSAGE;
|
||||
|
||||
if(argv[2] && !strcasecmp(argv[2],"recalc")) {
|
||||
z = argv[3] ? atoi(argv[3]) : 1;
|
||||
|
||||
if(z <= 0) {
|
||||
ast_cli(fd," C'mon let's be serious here... defaulting to 1.\n");
|
||||
z = 1;
|
||||
}
|
||||
|
||||
if(z > MAX_RECALC) {
|
||||
ast_cli(fd," Maximum limit of recalc exceeded by %d, truncating value to %d\n",z-MAX_RECALC,MAX_RECALC);
|
||||
z = MAX_RECALC;
|
||||
}
|
||||
ast_cli(fd," Recalculating Codec Translation (number of sample seconds: %d)\n\n",z);
|
||||
rebuild_matrix(z);
|
||||
|
||||
}
|
||||
|
||||
ast_cli(fd, " Translation times between formats (in milliseconds)\n");
|
||||
ast_cli(fd, " Source Format (Rows) Destination Format(Columns)\n\n");
|
||||
ast_mutex_lock(&list_lock);
|
||||
@@ -346,9 +377,11 @@ static int show_translation(int fd, int argc, char *argv[])
|
||||
static int added_cli = 0;
|
||||
|
||||
static char show_trans_usage[] =
|
||||
"Usage: show translation\n"
|
||||
"Usage: show translation [recalc] [<recalc seconds>]\n"
|
||||
" Displays known codec translators and the cost associated\n"
|
||||
"with each conversion.\n";
|
||||
"with each conversion. if the arguement 'recalc' is supplied along\n"
|
||||
"with optional number of seconds to test a new test will be performed\n"
|
||||
"as the chart is being displayed.\n";
|
||||
|
||||
static struct ast_cli_entry show_trans =
|
||||
{ { "show", "translation", NULL }, show_translation, "Display translation matrix", show_trans_usage };
|
||||
@@ -362,7 +395,7 @@ int ast_register_translator(struct ast_translator *t)
|
||||
ast_log(LOG_WARNING, "Format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
|
||||
return -1;
|
||||
}
|
||||
calc_cost(t);
|
||||
calc_cost(t,1);
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
|
||||
ast_mutex_lock(&list_lock);
|
||||
@@ -372,7 +405,7 @@ int ast_register_translator(struct ast_translator *t)
|
||||
}
|
||||
t->next = list;
|
||||
list = t;
|
||||
rebuild_matrix();
|
||||
rebuild_matrix(0);
|
||||
ast_mutex_unlock(&list_lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -396,7 +429,7 @@ int ast_unregister_translator(struct ast_translator *t)
|
||||
ul = u;
|
||||
u = u->next;
|
||||
}
|
||||
rebuild_matrix();
|
||||
rebuild_matrix(0);
|
||||
ast_mutex_unlock(&list_lock);
|
||||
return (u ? 0 : -1);
|
||||
}
|
||||
|
Reference in New Issue
Block a user