[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