[asterisk-commits] dvossel: branch dvossel/improved_hd_audio_translation_paths r280663 - in /tea...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Aug 2 15:07:41 CDT 2010


Author: dvossel
Date: Mon Aug  2 15:07:37 2010
New Revision: 280663

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=280663
Log:
build translation paths that avoid sample rate changes if at all possible

Modified:
    team/dvossel/improved_hd_audio_translation_paths/include/asterisk/translate.h
    team/dvossel/improved_hd_audio_translation_paths/main/cli.c
    team/dvossel/improved_hd_audio_translation_paths/main/translate.c

Modified: team/dvossel/improved_hd_audio_translation_paths/include/asterisk/translate.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/improved_hd_audio_translation_paths/include/asterisk/translate.h?view=diff&rev=280663&r1=280662&r2=280663
==============================================================================
--- team/dvossel/improved_hd_audio_translation_paths/include/asterisk/translate.h (original)
+++ team/dvossel/improved_hd_audio_translation_paths/include/asterisk/translate.h Mon Aug  2 15:07:37 2010
@@ -254,6 +254,12 @@
  */
 format_t ast_translate_available_formats(format_t dest, format_t src);
 
+/*!
+ * \brief Puts a string representation of the translation path into outbuf
+ * \retval on success, pointer to beginning of outbuf. on failure returns "".
+ */
+char *ast_translate_path_to_str(struct ast_trans_pvt *t, char *outbuf, size_t outlen);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: team/dvossel/improved_hd_audio_translation_paths/main/cli.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/improved_hd_audio_translation_paths/main/cli.c?view=diff&rev=280663&r1=280662&r2=280663
==============================================================================
--- team/dvossel/improved_hd_audio_translation_paths/main/cli.c (original)
+++ team/dvossel/improved_hd_audio_translation_paths/main/cli.c Mon Aug  2 15:07:37 2010
@@ -46,6 +46,7 @@
 #include "asterisk/lock.h"
 #include "editline/readline/readline.h"
 #include "asterisk/threadstorage.h"
+#include "asterisk/translate.h"
 
 /*!
  * \brief List of restrictions per user.
@@ -1342,7 +1343,7 @@
 	struct timeval now;
 	struct ast_str *out = ast_str_thread_get(&ast_str_thread_global_buf, 16);
 	char cdrtime[256];
-	char nf[256], wf[256], rf[256];
+	char nf[256], wf[256], rf[256], write_transpath[256], read_transpath[256];
 	long elapsed_seconds=0;
 	int hour=0, min=0, sec=0;
 #ifdef CHANNEL_TRACE
@@ -1398,8 +1399,8 @@
 		"  NativeFormats: %s\n"
 		"    WriteFormat: %s\n"
 		"     ReadFormat: %s\n"
-		" WriteTranscode: %s\n"
-		"  ReadTranscode: %s\n"
+		" WriteTranscode: %s %s\n"
+		"  ReadTranscode: %s %s\n"
 		"1st File Descriptor: %d\n"
 		"      Frames in: %d%s\n"
 		"     Frames out: %d%s\n"
@@ -1426,7 +1427,9 @@
 		ast_getformatname_multiple(wf, sizeof(wf), c->writeformat), 
 		ast_getformatname_multiple(rf, sizeof(rf), c->readformat),
 		c->writetrans ? "Yes" : "No",
+		ast_translate_path_to_str(c->writetrans, write_transpath, sizeof(write_transpath)),
 		c->readtrans ? "Yes" : "No",
+		ast_translate_path_to_str(c->readtrans, read_transpath, sizeof(read_transpath)),
 		c->fds[0],
 		c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
 		c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",

Modified: team/dvossel/improved_hd_audio_translation_paths/main/translate.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/improved_hd_audio_translation_paths/main/translate.c?view=diff&rev=280663&r1=280662&r2=280663
==============================================================================
--- team/dvossel/improved_hd_audio_translation_paths/main/translate.c (original)
+++ team/dvossel/improved_hd_audio_translation_paths/main/translate.c Mon Aug  2 15:07:37 2010
@@ -45,10 +45,23 @@
 /*! \brief the list of translators */
 static AST_RWLIST_HEAD_STATIC(translators, ast_translator);
 
+
+/*! \brief these values indicate how a translation path will affect the sample rate
+ *
+ *  \note These must stay in this order.  They are ordered by most optimal selection first.
+ */
+enum path_samp_change {
+	RATE_CHANGE_NONE = 0, /*! path uses the same sample rate consistently */
+	RATE_CHANGE_UPSAMP = 1,    /*! path will up the sample rate during a translation */
+	RATE_CHANGE_DOWNSAMP = 2,  /*! path will have to down the sample rate during a translation. */
+	RATE_CHANGE_UPSAMP_DOWNSAMP = 3, /*! path will both up and down the sample rate during translation */
+};
+
 struct translator_path {
 	struct ast_translator *step;	/*!< Next step translator */
 	unsigned int cost;		/*!< Complete cost to destination */
 	unsigned int multistep;		/*!< Multiple conversions required for this translation */
+	enum path_samp_change rate_change; /*!< does this path require a sample rate change, if so what kind. */
 };
 
 /*! \brief a matrix that, for any pair of supported formats,
@@ -402,6 +415,25 @@
 		t->cost = 1;
 }
 
+static enum path_samp_change get_rate_change_result(format_t src, format_t dst)
+{
+	int src_rate = ast_format_rate(src);
+	int dst_rate = ast_format_rate(dst);
+
+
+	/* if src rate is less than dst rate, a sample upgrade is required */
+	if (src_rate < dst_rate) {
+		return RATE_CHANGE_UPSAMP;
+	}
+
+	/* if src rate is larger than dst rate, a downgrade is required */
+	if (src_rate > dst_rate) {
+		return RATE_CHANGE_DOWNSAMP;
+	}
+
+	return RATE_CHANGE_NONE;
+}
+
 /*!
  * \brief rebuild a translation matrix.
  * \note This function expects the list of translators to be locked
@@ -409,6 +441,7 @@
 static void rebuild_matrix(int samples)
 {
 	struct ast_translator *t;
+	int new_rate_change;
 	int x;      /* source format index */
 	int y;      /* intermediate format index */
 	int z;      /* destination format index */
@@ -427,10 +460,21 @@
 
 		if (samples)
 			calc_cost(t, samples);
-	  
-		if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) {
+
+		new_rate_change = get_rate_change_result(1LL << t->srcfmt, 1LL << t->dstfmt);
+
+		/* this translator is the best choice if any of the below are true.
+		 * 1. no translation path is set between x and z yet.
+		 * 2. the new translation costs less and sample rate is no worse than old one. 
+		 * 3. the new translation has a better sample rate conversion than the old one.
+		 */
+		if (!tr_matrix[x][z].step ||
+			((t->cost < tr_matrix[x][z].cost) && (new_rate_change <= tr_matrix[x][z].rate_change)) ||
+			(new_rate_change < tr_matrix[x][z].rate_change)) {
+
 			tr_matrix[x][z].step = t;
 			tr_matrix[x][z].cost = t->cost;
+			tr_matrix[x][z].rate_change = new_rate_change;
 		}
 	}
 
@@ -447,8 +491,9 @@
 				if (x == y)                     /* skip ourselves */
 					continue;
 
-				for (z = 0; z<MAX_FORMAT; z++) {  /* dst format */
+				for (z = 0; z < MAX_FORMAT; z++) {  /* dst format */
 					int newcost;
+					int better_rate_conversion = 0;
 
 					if (z == x || z == y)       /* skip null conversions */
 						continue;
@@ -456,17 +501,52 @@
 						continue;
 					if (!tr_matrix[y][z].step)  /* no path from y to z */
 						continue;
+
+					/* Does x->y->z result in a less optimal sample rate change?
+					 * Never downgrade the sample rate conversion quality regardless
+					 * of any cost improvements */
+					if (tr_matrix[x][z].step &&
+						((tr_matrix[x][z].rate_change < tr_matrix[x][y].rate_change) ||
+						(tr_matrix[x][z].rate_change < tr_matrix[y][z].rate_change))) {
+						continue;
+					}
+
+					/* is x->y->z a better rate confersion that the current x->z? */
+					better_rate_conversion = (tr_matrix[x][z].step &&
+						(tr_matrix[x][z].rate_change > tr_matrix[x][y].rate_change) &&
+						(tr_matrix[x][z].rate_change > tr_matrix[y][z].rate_change)) ? 1 : 0;
+
 					newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost;
-					if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost)
-						continue;               /* x->y->z is more expensive than
-						                         * the existing path */
+					/* Is x->y->z more expensive the the existing path?
+					 * A higher quality sample rate conversion will always beat
+					 * a cost improvement though. */
+					if (!better_rate_conversion && tr_matrix[x][z].step && (newcost >= tr_matrix[x][z].cost)) {
+						continue;
+					}
+
 					/* ok, we can get from x to z via y with a cost that
 					   is the sum of the transition from x to y and
 					   from y to z */
-						 
 					tr_matrix[x][z].step = tr_matrix[x][y].step;
 					tr_matrix[x][z].cost = newcost;
 					tr_matrix[x][z].multistep = 1;
+
+					/* now calculate what kind of sample rate change is required for this multi-step path
+					 * 
+					 * if both paths require a change in rate, and they are not in the same direction
+					 * then this is a up sample down sample conversion scenario. */
+					if ((tr_matrix[x][y].rate_change > RATE_CHANGE_NONE) &&
+						(tr_matrix[y][z].rate_change > RATE_CHANGE_NONE) &&
+						(tr_matrix[x][y].rate_change != tr_matrix[y][z].rate_change)) {
+
+						tr_matrix[x][z].rate_change = RATE_CHANGE_UPSAMP_DOWNSAMP;
+					} else {
+						/* else just set the rate change to whichever is worse */
+						tr_matrix[x][z].rate_change = tr_matrix[x][y].rate_change > tr_matrix[y][z].rate_change
+							? tr_matrix[x][y].rate_change : tr_matrix[y][z].rate_change;
+					}
+
+
 					ast_debug(3, "Discovered %d cost path from %s to %s, via %s\n", tr_matrix[x][z].cost,
 						  ast_getformatname(1LL << x), ast_getformatname(1LL << z), ast_getformatname(1LL << y));
 					changed++;
@@ -478,9 +558,43 @@
 	}
 }
 
+char *ast_translate_path_to_str(struct ast_trans_pvt *p, char *outbuf, size_t outlen)
+{
+	struct ast_trans_pvt *pn = p;
+	char *orig_out = outbuf;
+	int namelen;
+	int writelen = 0;
+	if (!outbuf || !outlen) {
+		return "";
+	}
+
+	memset(outbuf, 0, outlen);
+
+	if (!p || !p->t) {
+		return "";
+	}
+
+	snprintf(outbuf, (outlen - writelen), "%s", ast_getformatname(1LL << p->t->srcfmt));
+	writelen = strlen(orig_out);
+	outbuf = orig_out + writelen;
+
+	while ( (p = pn) && (outlen > writelen)) {
+		pn = p->next;
+		namelen = strlen(p->t->name);
+		if ((outlen - writelen) < namelen) {
+			return "";
+		}
+		snprintf(outbuf, (outlen - writelen), "->%s", ast_getformatname(1LL << p->t->dstfmt));
+		writelen = strlen(orig_out);
+		outbuf = orig_out + writelen;
+	}
+
+	return orig_out;
+}
+
 static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-#define SHOW_TRANS 16
+#define SHOW_TRANS 64
 	int x, y, z;
 	int curlen = 0, longest = 0, magnitude[SHOW_TRANS] = { 0, };
 
@@ -526,22 +640,33 @@
 	ast_cli(a->fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
 	/* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
 	for (x = 0; x < SHOW_TRANS; x++) {
+		/* translation only applies to audio right now. */
+		if (!(AST_FORMAT_AUDIO_MASK & (1LL << (x))))
+			continue;
 		curlen = strlen(ast_getformatname(1LL << (x)));
 		if (curlen > longest)
 			longest = curlen;
 		for (y = 0; y < SHOW_TRANS; y++) {
+			if (!(AST_FORMAT_AUDIO_MASK & (1LL << (y))))
+				continue;
 			if (tr_matrix[x][y].cost > pow(10, magnitude[x])) {
 				magnitude[y] = floor(log10(tr_matrix[x][y].cost));
 			}
 		}
 	}
 	for (x = -1; x < SHOW_TRANS; x++) {
-		struct ast_str *out = ast_str_alloca(125);
+		struct ast_str *out = ast_str_alloca(256);
+		/* translation only applies to audio right now. */
+		if (x >= 0 && !(AST_FORMAT_AUDIO_MASK & (1LL << (x))))
+			continue;
 		/*Go ahead and move to next iteration if dealing with an unknown codec*/
 		if(x >= 0 && !strcmp(ast_getformatname(1LL << (x)), "unknown"))
 			continue;
 		ast_str_set(&out, -1, " ");
 		for (y = -1; y < SHOW_TRANS; y++) {
+			/* translation only applies to audio right now. */
+			if (y >= 0 && !(AST_FORMAT_AUDIO_MASK & (1LL << (y))))
+				continue;
 			/*Go ahead and move to next iteration if dealing with an unknown codec*/
 			if (y >= 0 && !strcmp(ast_getformatname(1LL << (y)), "unknown"))
 				continue;




More information about the asterisk-commits mailing list