mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 12:36:58 +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 <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define MAX_RECALC 200 /* max sample recalc */
|
||||||
|
|
||||||
/* This could all be done more efficiently *IF* we chained packets together
|
/* This could all be done more efficiently *IF* we chained packets together
|
||||||
by default, but it would also complicate virtually every application. */
|
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;
|
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;
|
struct ast_translator *t;
|
||||||
int changed;
|
int changed;
|
||||||
@@ -230,6 +280,9 @@ static void rebuild_matrix(void)
|
|||||||
bzero(tr_matrix, sizeof(tr_matrix));
|
bzero(tr_matrix, sizeof(tr_matrix));
|
||||||
t = list;
|
t = list;
|
||||||
while(t) {
|
while(t) {
|
||||||
|
if(samples)
|
||||||
|
calc_cost(t,samples);
|
||||||
|
|
||||||
if (!tr_matrix[t->srcfmt][t->dstfmt].step ||
|
if (!tr_matrix[t->srcfmt][t->dstfmt].step ||
|
||||||
tr_matrix[t->srcfmt][t->dstfmt].cost > t->cost) {
|
tr_matrix[t->srcfmt][t->dstfmt].cost > t->cost) {
|
||||||
tr_matrix[t->srcfmt][t->dstfmt].step = t;
|
tr_matrix[t->srcfmt][t->dstfmt].step = t;
|
||||||
@@ -267,57 +320,35 @@ static void rebuild_matrix(void)
|
|||||||
} while (changed);
|
} 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[])
|
static int show_translation(int fd, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
#define SHOW_TRANS 11
|
#define SHOW_TRANS 11
|
||||||
int x,y;
|
int x,y,z;
|
||||||
char line[80];
|
char line[80];
|
||||||
if (argc != 2)
|
if (argc > 4)
|
||||||
return RESULT_SHOWUSAGE;
|
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, " Translation times between formats (in milliseconds)\n");
|
||||||
ast_cli(fd, " Source Format (Rows) Destination Format(Columns)\n\n");
|
ast_cli(fd, " Source Format (Rows) Destination Format(Columns)\n\n");
|
||||||
ast_mutex_lock(&list_lock);
|
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 int added_cli = 0;
|
||||||
|
|
||||||
static char show_trans_usage[] =
|
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"
|
" 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 =
|
static struct ast_cli_entry show_trans =
|
||||||
{ { "show", "translation", NULL }, show_translation, "Display translation matrix", show_trans_usage };
|
{ { "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));
|
ast_log(LOG_WARNING, "Format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
calc_cost(t);
|
calc_cost(t,1);
|
||||||
if (option_verbose > 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_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);
|
ast_mutex_lock(&list_lock);
|
||||||
@@ -372,7 +405,7 @@ int ast_register_translator(struct ast_translator *t)
|
|||||||
}
|
}
|
||||||
t->next = list;
|
t->next = list;
|
||||||
list = t;
|
list = t;
|
||||||
rebuild_matrix();
|
rebuild_matrix(0);
|
||||||
ast_mutex_unlock(&list_lock);
|
ast_mutex_unlock(&list_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -396,7 +429,7 @@ int ast_unregister_translator(struct ast_translator *t)
|
|||||||
ul = u;
|
ul = u;
|
||||||
u = u->next;
|
u = u->next;
|
||||||
}
|
}
|
||||||
rebuild_matrix();
|
rebuild_matrix(0);
|
||||||
ast_mutex_unlock(&list_lock);
|
ast_mutex_unlock(&list_lock);
|
||||||
return (u ? 0 : -1);
|
return (u ? 0 : -1);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user