[asterisk-commits] dvossel: branch dvossel/fixtheworld_phase1_step2 r299491 - /team/dvossel/fixt...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Dec 22 22:50:07 UTC 2010
Author: dvossel
Date: Wed Dec 22 16:50:05 2010
New Revision: 299491
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=299491
Log: (empty)
Modified:
team/dvossel/fixtheworld_phase1_step2/main/translate.c
Modified: team/dvossel/fixtheworld_phase1_step2/main/translate.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/fixtheworld_phase1_step2/main/translate.c?view=diff&rev=299491&r1=299490&r2=299491
==============================================================================
--- team/dvossel/fixtheworld_phase1_step2/main/translate.c (original)
+++ team/dvossel/fixtheworld_phase1_step2/main/translate.c Wed Dec 22 16:50:05 2010
@@ -40,12 +40,14 @@
#include "asterisk/cli.h"
#include "asterisk/term.h"
-#define MAX_RECALC 1000 /* max sample recalc */
-
-/*! This value is used to define how large the matrix( and tr_index2format arrays
- * are defined to be in memory by default. Once Asterisk can represent more formats
- * than this number represents with translation, increase it. */
-#define DEFAULT_INDEX_SIZE 128
+/*! \todo
+ * TODO: sample frames for each supported input format.
+ * We build this on the fly, by taking an SLIN frame and using
+ * the existing converter to play with it.
+ */
+
+/*! max sample recalc */
+#define MAX_RECALC 1000
/*! \brief the list of translators */
static AST_RWLIST_HEAD_STATIC(translators, ast_translator);
@@ -56,7 +58,8 @@
uint8_t multistep; /*!< Multiple conversions required for this translation */
} __attribute__((packed));
-/*! \brief a matrix that, for any pair of supported formats,
+/*!
+ * \brief a matrix that, for any pair of supported formats,
* indicates the total cost of translation and the first step.
* The full path can be reconstricted iterating on the matrix
* until step->dstfmt == desired_format.
@@ -66,39 +69,76 @@
* Note: the lock in the 'translators' list is also used to protect
* this structure.
*/
-static struct translator_path __matrix[DEFAULT_INDEX_SIZE][DEFAULT_INDEX_SIZE];
-/*! table for converting index to format id values. */
-static format_t tr_index2format[DEFAULT_INDEX_SIZE];
-/*! the current largest index used by the matrix( and tr_index2format tables */
-static int cur_max_index = 0;
-
-/*! \todo
- * TODO: sample frames for each supported input format.
- * We build this on the fly, by taking an SLIN frame and using
- * the existing converter to play with it.
- */
+static struct translator_path **__matrix;
+
+/*!
+ * \brief table for converting index to format id values.
+ *
+ * \note this table is protected by the table_lock.
+ */
+static format_t *__indextable;
+
+/*! protects the __indextable for resizing */
+static ast_rwlock_t tablelock;
+
+/* index size starts at this*/
+#define INIT_INDEX 24
+/* index size grows by this as necessary */
+#define GROW_INDEX 8
+
+/*! the current largest index used by the matrix_get( and __indextable tables */
+static int cur_max_index;
+/*! the largest index that can be used in eithr the __indextable or __matrix before resize must occur */
+static int index_size;
+
+static void matrix_rebuild(int samples);
/*!
* \internal
* \brief converts format id to index value.
*/
-static force_inline int format2index(format_t id)
+static int format2index(format_t id)
{
int x;
+
+ ast_rwlock_rdlock(&tablelock);
for (x = 0; x < cur_max_index; x++) {
- if (tr_index2format[x] == id) {
+ if (__indextable[x] == id) {
/* format already exists in index2format table */
+ ast_rwlock_unlock(&tablelock);
return x;
}
}
-
- if (cur_max_index == (DEFAULT_INDEX_SIZE)) {
+ ast_rwlock_unlock(&tablelock);
+ return -1; /* not found */
+}
+
+/*
+ * \internal
+ * \brief add a new format to the matrix and index table structures.
+ *
+ * \note it is perfectly safe to call this on formats already indexed.
+ *
+ * \retval 0, success
+ * \retval -1, matrix and index table need to be resized
+ */
+static int add_format2index(format_t id)
+{
+ if (format2index(id) != -1) {
+ /* format is already already indexed */
+ return 0;
+ }
+
+ ast_rwlock_wrlock(&tablelock);
+ if (cur_max_index == (index_size)) {
+ ast_rwlock_unlock(&tablelock);
return -1; /* hit max length. todohere, make it grow. */
}
- tr_index2format[cur_max_index] = id;
+ __indextable[cur_max_index] = id;
cur_max_index++;
-
- return cur_max_index - 1;
+ ast_rwlock_unlock(&tablelock);
+
+ return 0;
}
/*!
@@ -107,13 +147,116 @@
*/
static force_inline format_t index2format(int index)
{
- return tr_index2format[index];
-}
-
-
-static struct translator_path *matrix(int x, int y)
-{
- return &__matrix[x][y];
+ format_t format;
+
+ ast_rwlock_rdlock(&tablelock);
+ format = __indextable[index];
+ ast_rwlock_unlock(&tablelock);
+
+ return format;
+}
+
+/*
+ * \internal
+ * \brief resize both the matrix and index table so they can represent
+ * more translators
+ *
+ * \note _NO_ locks can be held prior to calling this function
+ *
+ * \retval 0, success
+ * \retval -1, failure. Old matrix and index table can still be used though
+ */
+static int matrix_resize(int init)
+{
+ struct translator_path **tmp_matrix = NULL;
+ format_t *tmp_table = NULL;
+ int old_index;
+ int x;
+
+ AST_RWLIST_WRLOCK(&translators);
+ ast_rwlock_wrlock(&tablelock);
+
+ old_index = index_size;
+ if (init) {
+ index_size += INIT_INDEX;
+ } else {
+ index_size += GROW_INDEX;
+ }
+
+ /* make new 2d array of translator_path structures */
+ if (!(tmp_matrix = ast_calloc(1, sizeof(struct translator_path *) * (index_size)))) {
+ goto resize_cleanup;
+ }
+
+ for (x = 0; x < index_size; x++) {
+ if (!(tmp_matrix[x] = ast_calloc(1, sizeof(struct translator_path) * (index_size)))) {
+ goto resize_cleanup;
+ }
+ }
+
+ /* make new index table */
+ if (!(tmp_table = ast_calloc(1, sizeof(format_t) * index_size))) {
+ goto resize_cleanup;
+ }
+
+ /* if everything went well this far, free the old and use the new */
+ if (!init) {
+ for (x = 0; x < old_index; x++) {
+ ast_free(__matrix[x]);
+ }
+ ast_free(__matrix);
+
+ memcpy(tmp_table, __indextable, sizeof(format_t) * old_index);
+ ast_free(__indextable);
+ }
+
+ /* now copy them over */
+ __matrix = tmp_matrix;
+ __indextable = tmp_table;
+
+ matrix_rebuild(0);
+ ast_rwlock_unlock(&tablelock);
+ AST_RWLIST_UNLOCK(&translators);
+
+ return 0;
+
+resize_cleanup:
+ ast_rwlock_unlock(&tablelock);
+ AST_RWLIST_UNLOCK(&translators);
+ if (tmp_matrix) {
+ for (x = 0; x < index_size; x++) {
+ ast_free(tmp_matrix[x]);
+ }
+ ast_free(tmp_matrix);
+ }
+ ast_free(tmp_table);
+
+ return -1;
+}
+
+/*!
+ * \internal
+ * \brief reinitialize the __matrix during matrix rebuild
+ *
+ * \note must be protected by the translators list lock
+ */
+static void matrix_clear(void)
+{
+ int x;
+ for (x = 0; x < index_size; x++) {
+ memset(__matrix[x], '\0', sizeof(struct translator_path) * (index_size));
+ }
+}
+
+/*!
+ * \internal
+ * \brief get a matrix entry
+ *
+ * \note This function must be protected by the translators list lock
+ */
+static struct translator_path *matrix_get(int x, int y)
+{
+ return __matrix[x] + y;
}
/*
@@ -272,7 +415,7 @@
while (source != dest) {
struct ast_trans_pvt *cur;
- struct ast_translator *t = matrix(source, dest)->step;
+ struct ast_translator *t = matrix_get(source, dest)->step;
if (!t) {
ast_log(LOG_WARNING, "No translator path from %s to %s\n",
ast_getformatname(source), ast_getformatname(dest));
@@ -521,7 +664,7 @@
* \brief rebuild a translation matrix.
* \note This function expects the list of translators to be locked
*/
-static void rebuild_matrix(int samples)
+static void matrix_rebuild(int samples)
{
struct ast_translator *t;
int newtablecost;
@@ -531,7 +674,7 @@
ast_debug(1, "Resetting translation matrix\n");
- memset(__matrix, '\0', sizeof(__matrix));
+ matrix_clear();
/* first, compute all direct costs */
AST_RWLIST_TRAVERSE(&translators, t, list) {
@@ -552,12 +695,12 @@
* 3. the new computational cost is less. Computational cost is only used
* to break a tie between two identical translation paths.
*/
- if (!matrix(x, z)->step ||
- (t->table_cost < matrix(x, z)->step->table_cost) ||
- (t->comp_cost < matrix(x, z)->step->comp_cost)) {
-
- matrix(x, z)->step = t;
- matrix(x, z)->table_cost = t->table_cost;
+ if (!matrix_get(x, z)->step ||
+ (t->table_cost < matrix_get(x, z)->step->table_cost) ||
+ (t->comp_cost < matrix_get(x, z)->step->comp_cost)) {
+
+ matrix_get(x, z)->step = t;
+ matrix_get(x, z)->table_cost = t->table_cost;
}
}
@@ -576,23 +719,23 @@
}
for (z = 0; z < cur_max_index; z++) { /* dst format */
if ((z == x || z == y) || /* skip null conversions */
- !matrix(x, y)->step || /* no path from x to y */
- !matrix(y, z)->step) { /* no path from y to z */
+ !matrix_get(x, y)->step || /* no path from x to y */
+ !matrix_get(y, z)->step) { /* no path from y to z */
continue;
}
/* calculate table cost from x->y->z */
- newtablecost = matrix(x, y)->table_cost + matrix(y, z)->table_cost;
+ newtablecost = matrix_get(x, y)->table_cost + matrix_get(y, z)->table_cost;
/* if no step already exists between x and z OR the new cost of using the intermediate
* step is cheaper, use this step. */
- if (!matrix(x, z)->step || (newtablecost < matrix(x, z)->table_cost)) {
- matrix(x, z)->step = matrix(x, y)->step;
- matrix(x, z)->table_cost = newtablecost;
- matrix(x, z)->multistep = 1;
+ if (!matrix_get(x, z)->step || (newtablecost < matrix_get(x, z)->table_cost)) {
+ matrix_get(x, z)->step = matrix_get(x, y)->step;
+ matrix_get(x, z)->table_cost = newtablecost;
+ matrix_get(x, z)->multistep = 1;
changed++;
ast_debug(3, "Discovered %d cost path from %s to %s, via %s\n",
- matrix(x, z)->table_cost,
+ matrix_get(x, z)->table_cost,
ast_getformatname(index2format(x)),
ast_getformatname(index2format(z)),
ast_getformatname(index2format(y)));
@@ -660,7 +803,7 @@
}
ast_cli(a->fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", time);
AST_RWLIST_WRLOCK(&translators);
- rebuild_matrix(time);
+ matrix_rebuild(time);
AST_RWLIST_UNLOCK(&translators);
}
@@ -711,9 +854,9 @@
curlen = 5;
}
- if (x >= 0 && y >= 0 && matrix(x, y)->step) {
+ if (x >= 0 && y >= 0 && matrix_get(x, y)->step) {
/* Actual codec output */
- ast_str_append(&out, -1, "%*d", curlen + 1, (matrix(x, y)->table_cost/100));
+ ast_str_append(&out, -1, "%*d", curlen + 1, (matrix_get(x, y)->table_cost/100));
} else if (x == -1 && y >= 0) {
/* Top row - use a dynamic size */
ast_str_append(&out, -1, "%*s", curlen + 1, ast_getformatname(index2format(y)) );
@@ -769,10 +912,10 @@
dst = format2index(format_list[i].bits);
src = format2index(input_src);
ast_str_reset(str);
- if (matrix(src, dst)->step) {
- ast_str_append(&str, 0, "%s", ast_getformatname(index2format(matrix(src, dst)->step->srcfmt)));
+ if ((len >= cur_max_index) && (src != -1) && (dst != -1) && matrix_get(src, dst)->step) {
+ ast_str_append(&str, 0, "%s", ast_getformatname(index2format(matrix_get(src, dst)->step->srcfmt)));
while (src != dst) {
- step = matrix(src, dst)->step;
+ step = matrix_get(src, dst)->step;
if (!step) {
ast_str_reset(str);
break;
@@ -844,6 +987,12 @@
struct ast_translator *u;
char tmp[80];
+ if (add_format2index(t->srcfmt) || add_format2index(t->dstfmt)) {
+ matrix_resize(0);
+ add_format2index(t->srcfmt);
+ add_format2index(t->dstfmt);
+ }
+
if (!mod) {
ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
return -1;
@@ -925,7 +1074,7 @@
AST_RWLIST_INSERT_HEAD(&translators, t, list);
}
- rebuild_matrix(0);
+ matrix_rebuild(0);
AST_RWLIST_UNLOCK(&translators);
@@ -954,7 +1103,7 @@
AST_RWLIST_TRAVERSE_SAFE_END;
if (found) {
- rebuild_matrix(0);
+ matrix_rebuild(0);
}
AST_RWLIST_UNLOCK(&translators);
@@ -966,7 +1115,7 @@
{
AST_RWLIST_WRLOCK(&translators);
t->active = 1;
- rebuild_matrix(0);
+ matrix_rebuild(0);
AST_RWLIST_UNLOCK(&translators);
}
@@ -974,7 +1123,7 @@
{
AST_RWLIST_WRLOCK(&translators);
t->active = 0;
- rebuild_matrix(0);
+ matrix_rebuild(0);
AST_RWLIST_UNLOCK(&translators);
}
@@ -1016,15 +1165,15 @@
continue;
}
for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) {
- if (!(*srcs & cursrc) || !matrix(x, y)->step) {
+ if (!(*srcs & cursrc) || !matrix_get(x, y)->step) {
continue;
}
- if ((matrix(x, y)->table_cost < besttablecost || matrix(x, y)->multistep < beststeps)) {
+ if ((matrix_get(x, y)->table_cost < besttablecost || matrix_get(x, y)->multistep < beststeps)) {
/* better than what we have so far */
best = cursrc;
bestdst = cur;
- besttablecost = matrix(x, y)->table_cost;
- beststeps = matrix(x, y)->multistep;
+ besttablecost = matrix_get(x, y)->table_cost;
+ beststeps = matrix_get(x, y)->multistep;
}
}
}
@@ -1052,8 +1201,8 @@
}
AST_RWLIST_RDLOCK(&translators);
- if (matrix(src, dest)->step) {
- res = matrix(src, dest)->multistep + 1;
+ if (matrix_get(src, dest)->step) {
+ res = matrix_get(src, dest)->multistep + 1;
}
AST_RWLIST_UNLOCK(&translators);
@@ -1110,13 +1259,13 @@
/* if we don't have a translation path from the src
to this format, remove it from the result */
- if (!matrix(src_audio, index)->step) {
+ if (!matrix_get(src_audio, index)->step) {
res &= ~tmp_fmt;
continue;
}
/* now check the opposite direction */
- if (!matrix(index, src_audio)->step) {
+ if (!matrix_get(index, src_audio)->step) {
res &= tmp_fmt;
}
}
@@ -1144,13 +1293,13 @@
/* if we don't have a translation path from the src
to this format, remove it from the result */
- if (!matrix(src_video, index)->step) {
+ if (!matrix_get(src_video, index)->step) {
res &= ~tmp_fmt;
continue;
}
/* now check the opposite direction */
- if (!matrix(index, src_video)->step) {
+ if (!matrix_get(index, src_video)->step) {
res &= ~tmp_fmt;
}
}
@@ -1163,24 +1312,6 @@
int ast_translate_init(void)
{
- //index_size = DEFAULT_INDEX_SIZE;
- /* 2d array of translator_path structures */
-// if (!(t = ast_calloc(1, sizeof(struct translator_path) * ((index_size) * (index_size))))) {
-// return -1;
-// }
-
- //for (x = 0; x < index_size; x++) {
-// if (!(matrix([x] = ast_calloc(1, sizeof(struct translator_path) * (index_size)))) {
-// /* this will kill Asterisk on startup, so no reason to clean up */
-// return -1;
-// }
-// }
-
- /* 1d array of format_t IDs */
-// if (!(tr_index2format = ast_calloc(1, sizeof(format_t) * (index_size)))) {
-// ast_free(t);
-// return -1;
-// }
- return 0;
-
-}
+ ast_rwlock_init(&tablelock);
+ return matrix_resize(1);
+}
More information about the asterisk-commits
mailing list