[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