[asterisk-commits] tilghman: branch group/codec_bits r113646 - in /team/group/codec_bits: includ...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Apr 8 23:23:11 CDT 2008
Author: tilghman
Date: Tue Apr 8 23:23:11 2008
New Revision: 113646
URL: http://svn.digium.com/view/asterisk?view=rev&rev=113646
Log:
Translations and the core is done, but boy is it ever slow...
Modified:
team/group/codec_bits/include/asterisk/slinfactory.h
team/group/codec_bits/main/frame.c
team/group/codec_bits/main/rtp.c
team/group/codec_bits/main/slinfactory.c
team/group/codec_bits/main/translate.c
Modified: team/group/codec_bits/include/asterisk/slinfactory.h
URL: http://svn.digium.com/view/asterisk/team/group/codec_bits/include/asterisk/slinfactory.h?view=diff&rev=113646&r1=113645&r2=113646
==============================================================================
--- team/group/codec_bits/include/asterisk/slinfactory.h (original)
+++ team/group/codec_bits/include/asterisk/slinfactory.h Tue Apr 8 23:23:11 2008
@@ -28,6 +28,8 @@
extern "C" {
#endif
+#include "asterisk/frame.h"
+
#define AST_SLINFACTORY_MAX_HOLD 1280
struct ast_slinfactory {
@@ -37,7 +39,7 @@
short *offset; /*!< Offset into the hold where audio begins */
size_t holdlen; /*!< Number of samples currently in the hold */
unsigned int size; /*!< Number of samples currently in the factory */
- unsigned int format; /*!< Current format the translation path is converting from */
+ struct ast_extended_codec format; /*!< Current format the translation path is converting from */
};
/*!
Modified: team/group/codec_bits/main/frame.c
URL: http://svn.digium.com/view/asterisk/team/group/codec_bits/main/frame.c?view=diff&rev=113646&r1=113645&r2=113646
==============================================================================
--- team/group/codec_bits/main/frame.c (original)
+++ team/group/codec_bits/main/frame.c Tue Apr 8 23:23:11 2008
@@ -52,6 +52,7 @@
const struct ast_extended_codec AST_FMT_VIDEO_MASK = { .video = { -1, -1, -1, -1, -1, -1, -1 }, };
const struct ast_extended_codec AST_FMT_IMAGE_MASK = { .image = { -1 } };
const struct ast_extended_codec AST_FMT_TEXT_MASK = { .text = { -1 } };
+const struct ast_extended_codec AST_FMT_NULL_MASK = { { 0 } };
#if !defined(LOW_MEMORY)
static void frame_cache_cleanup(void *data);
Modified: team/group/codec_bits/main/rtp.c
URL: http://svn.digium.com/view/asterisk/team/group/codec_bits/main/rtp.c?view=diff&rev=113646&r1=113645&r2=113646
==============================================================================
--- team/group/codec_bits/main/rtp.c (original)
+++ team/group/codec_bits/main/rtp.c Tue Apr 8 23:23:11 2008
@@ -1345,7 +1345,7 @@
return -1;
/* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
- if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
+ if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.u.code == AST_RTP_DTMF)
return -1;
/* Otherwise adjust bridged payload to match */
@@ -1566,7 +1566,7 @@
struct ast_frame *f = NULL;
/* This is special in-band data that's not one of our codecs */
- if (rtpPT.code == AST_RTP_DTMF) {
+ if (rtpPT.u.code == AST_RTP_DTMF) {
/* It's special -- rfc2833 process it */
if (rtp_debug_test_addr(&sin)) {
unsigned char *data;
@@ -1584,13 +1584,13 @@
ast_verbose("Got RTP RFC2833 from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
}
f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp);
- } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
+ } else if (rtpPT.u.code == AST_RTP_CISCO_DTMF) {
/* It's really special -- process it the Cisco way */
if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) {
f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
rtp->lastevent = seqno;
}
- } else if (rtpPT.code == AST_RTP_CN) {
+ } else if (rtpPT.u.code == AST_RTP_CN) {
/* Comfort Noise */
f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
} else {
@@ -1598,7 +1598,7 @@
}
return f ? f : &ast_null_frame;
}
- rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
+ rtp->lastrxformat = rtp->f.subclass = rtpPT.u.code;
rtp->f.frametype = FMT_NZ(FMT_AND(rtp->f.codec, AST_FMT_AUDIO_MASK)) ? AST_FRAME_VOICE : FMT_NZ(FMT_AND(rtp->f.codec, AST_FMT_VIDEO_MASK)) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
if (!rtp->lastrxts)
@@ -1614,16 +1614,17 @@
rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
rtp->f.seqno = seqno;
- if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
+ if (FMT_NZ(FMT_AND(rtp->f.codec, AST_FMT_AUDIO_MASK))) {
rtp->f.samples = ast_codec_get_samples(&rtp->f);
- if (rtp->f.subclass == AST_FORMAT_SLINEAR)
+ if (FMT_EQ(rtp->f.codec, AST_FMT_SLINEAR)) {
ast_frame_byteswap_be(&rtp->f);
+ }
calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
/* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
rtp->f.ts = timestamp / 8;
- rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 );
- } else if(rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
+ rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.codec) == 16000) ? 16 : 8 );
+ } else if (FMT_NZ(FMT_AND(rtp->f.codec, AST_FMT_VIDEO_MASK))) {
/* Video -- samples is # of samples vs. 90000 */
if (!rtp->lastividtimestamp)
rtp->lastividtimestamp = timestamp;
@@ -1698,37 +1699,37 @@
* assigned values
*/
static struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] = {
- [0] = {1, { .codec = { .audio = { AST_FORMAT_ULAW } } } },
+ [0] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_ULAW } } } },
#ifdef USE_DEPRECATED_G726
- [2] = {1, { .codec = { .audio = { AST_FORMAT_G726 } } } }, /* Technically this is G.721, but if Cisco can do it, so can we... */
+ [2] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_G726 } } } }, /* Technically this is G.721, but if Cisco can do it, so can we... */
#endif
- [3] = {1, { .codec = { .audio = { AST_FORMAT_GSM } } } },
- [4] = {1, { .codec = { .audio = { AST_FORMAT_G723_1 } } } },
- [5] = {1, { .codec = { .audio = { AST_FORMAT_ADPCM } } } }, /* 8 kHz */
- [6] = {1, { .codec = { .audio = { AST_FORMAT_ADPCM } } } }, /* 16 kHz */
- [7] = {1, { .codec = { .audio = { AST_FORMAT_LPC10 } } } },
- [8] = {1, { .codec = { .audio = { AST_FORMAT_ALAW } } } },
- [9] = {1, { .codec = { .audio = { AST_FORMAT_G722 } } } },
- [10] = {1, { .codec = { .audio = { AST_FORMAT_SLINEAR } } } }, /* 2 channels */
- [11] = {1, { .codec = { .audio = { AST_FORMAT_SLINEAR } } } }, /* 1 channel */
+ [3] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_GSM } } } },
+ [4] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_G723_1 } } } },
+ [5] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_ADPCM } } } }, /* 8 kHz */
+ [6] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_ADPCM } } } }, /* 16 kHz */
+ [7] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_LPC10 } } } },
+ [8] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_ALAW } } } },
+ [9] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_G722 } } } },
+ [10] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_SLINEAR } } } }, /* 2 channels */
+ [11] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_SLINEAR } } } }, /* 1 channel */
[13] = {0, { .code = AST_RTP_CN } },
- [16] = {1, { .codec = { .audio = { AST_FORMAT_ADPCM } } } }, /* 11.025 kHz */
- [17] = {1, { .codec = { .audio = { AST_FORMAT_ADPCM } } } }, /* 22.050 kHz */
- [18] = {1, { .codec = { .audio = { AST_FORMAT_G729A } } } },
+ [16] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_ADPCM } } } }, /* 11.025 kHz */
+ [17] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_ADPCM } } } }, /* 22.050 kHz */
+ [18] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_G729A } } } },
[19] = {0, { .code = AST_RTP_CN } }, /* Also used for CN */
- [26] = {1, { .codec = { .image = { AST_FORMAT_JPEG } } } },
- [31] = {1, { .codec = { .video = { AST_FORMAT_H261 } } } },
- [34] = {1, { .codec = { .video = { AST_FORMAT_H263 } } } },
- [97] = {1, { .codec = { .audio = { AST_FORMAT_ILBC } } } },
- [98] = {1, { .codec = { .video = { AST_FORMAT_H263_PLUS } } } },
- [99] = {1, { .codec = { .video = { AST_FORMAT_H264 } } } },
+ [26] = {1, { .codec = { .image = { AST_FORMAT_IMAGE_JPEG } } } },
+ [31] = {1, { .codec = { .video = { AST_FORMAT_VIDEO_H261 } } } },
+ [34] = {1, { .codec = { .video = { AST_FORMAT_VIDEO_H263 } } } },
+ [97] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_ILBC } } } },
+ [98] = {1, { .codec = { .video = { AST_FORMAT_VIDEO_H263_PLUS } } } },
+ [99] = {1, { .codec = { .video = { AST_FORMAT_VIDEO_H264 } } } },
[101] = {0, { .code = AST_RTP_DTMF } },
- [102] = {1, { .codec = { .text = { AST_FORMAT_T140 } } } }, /* Real time text chat */
- [103] = {1, { .codec = { .video = { AST_FORMAT_H263_PLUS } } } },
- [104] = {1, { .codec = { .video = { AST_FORMAT_MP4_VIDEO } } } },
- [110] = {1, { .codec = { .audio = { AST_FORMAT_SPEEX } } } },
- [111] = {1, { .codec = { .audio = { AST_FORMAT_G726 } } } },
- [112] = {1, { .codec = { .audio = { AST_FORMAT_G726_AAL2 } } } },
+ [102] = {1, { .codec = { .text = { AST_FORMAT_TEXT_T140 } } } }, /* Real time text chat */
+ [103] = {1, { .codec = { .video = { AST_FORMAT_VIDEO_H263_PLUS } } } },
+ [104] = {1, { .codec = { .video = { AST_FORMAT_VIDEO_MP4_VIDEO } } } },
+ [110] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_SPEEX } } } },
+ [111] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_G726 } } } },
+ [112] = {1, { .codec = { .audio = { AST_FORMAT_AUDIO_G726_AAL2 } } } },
[121] = {0, { .code = AST_RTP_CISCO_DTMF } }, /* Must be type 121 */
};
@@ -1743,7 +1744,7 @@
for (i = 0; i < MAX_RTP_PT; ++i) {
rtp->current_RTP_PT[i].isAstFormat = 0;
- rtp->current_RTP_PT[i].code = 0;
+ rtp->current_RTP_PT[i].u.code = 0;
}
rtp->rtp_lookup_code_cache_isAstFormat = 0;
@@ -1762,7 +1763,7 @@
/* Initialize to default payload types */
for (i = 0; i < MAX_RTP_PT; ++i) {
rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
- rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
+ rtp->current_RTP_PT[i].u.code = static_RTP_PT[i].u.code;
}
rtp->rtp_lookup_code_cache_isAstFormat = 0;
@@ -1782,8 +1783,8 @@
for (i = 0; i < MAX_RTP_PT; ++i) {
dest->current_RTP_PT[i].isAstFormat =
src->current_RTP_PT[i].isAstFormat;
- dest->current_RTP_PT[i].code =
- src->current_RTP_PT[i].code;
+ dest->current_RTP_PT[i].u.code =
+ src->current_RTP_PT[i].u.code;
}
dest->rtp_lookup_code_cache_isAstFormat = 0;
dest->rtp_lookup_code_cache.codec = AST_FMT_NULL_MASK;
@@ -1875,7 +1876,7 @@
else
destcodec = AST_FMT_NULL_MASK;
/* Ensure we have at least one matching codec */
- if (!(srccodec & destcodec)) {
+ if (FMT_NOT(FMT_AND(srccodec, destcodec))) {
ast_channel_unlock(c0);
if (c1)
ast_channel_unlock(c1);
@@ -1904,7 +1905,7 @@
struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED;
- int srccodec, destcodec;
+ struct ast_extended_codec srccodec, destcodec;
/* Lock channels */
ast_channel_lock(dest);
@@ -1940,14 +1941,14 @@
if (srcpr->get_codec)
srccodec = srcpr->get_codec(src);
else
- srccodec = 0;
+ srccodec = AST_FMT_NULL_MASK;
if (destpr->get_codec)
destcodec = destpr->get_codec(dest);
else
- destcodec = 0;
+ destcodec = AST_FMT_NULL_MASK;
/* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
- if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) {
+ if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || FMT_NOT(FMT_AND(srccodec, destcodec))) {
/* Somebody doesn't want to play... */
ast_channel_unlock(dest);
ast_channel_unlock(src);
@@ -1975,7 +1976,7 @@
*/
void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt)
{
- if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0)
+ if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].u.code == 0)
return; /* bogus payload type */
rtp_bridge_lock(rtp);
@@ -1992,7 +1993,7 @@
rtp_bridge_lock(rtp);
rtp->current_RTP_PT[pt].isAstFormat = 0;
- rtp->current_RTP_PT[pt].code = 0;
+ rtp->current_RTP_PT[pt].u.code = 0;
rtp_bridge_unlock(rtp);
}
@@ -2017,11 +2018,11 @@
strcasecmp(mimeType, mimeTypes[i].type) == 0) {
found = 1;
rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
- if ((mimeTypes[i].payloadType.u.codec.audio[0] == AST_FORMAT_G726) &&
+ if ((mimeTypes[i].payloadType.u.codec.audio[0] == AST_FORMAT_AUDIO_G726) &&
mimeTypes[i].payloadType.isAstFormat &&
(options & AST_RTP_OPT_G726_NONSTANDARD)) {
- rtp->current_RTP_PT[pt].codec = AST_FMT_NULL_MASK;
- rtp->current_RTP_PT[pt].codec.audio[0] = AST_FORMAT_AUDIO_G726_AAL2;
+ rtp->current_RTP_PT[pt].u.codec = AST_FMT_NULL_MASK;
+ rtp->current_RTP_PT[pt].u.codec.audio[0] = AST_FORMAT_AUDIO_G726_AAL2;
}
break;
}
@@ -2167,7 +2168,7 @@
for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
if (FMT_EQ(mimeTypes[i].payloadType.u.codec, code) && (mimeTypes[i].payloadType.isAstFormat == 1)) {
- if ((code == AST_FORMAT_G726_AAL2) &&
+ if ((code.audio[0] == AST_FORMAT_AUDIO_G726_AAL2) &&
(options & AST_RTP_OPT_G726_NONSTANDARD))
return "G726-32";
else
Modified: team/group/codec_bits/main/slinfactory.c
URL: http://svn.digium.com/view/asterisk/team/group/codec_bits/main/slinfactory.c?view=diff&rev=113646&r1=113645&r2=113646
==============================================================================
--- team/group/codec_bits/main/slinfactory.c (original)
+++ team/group/codec_bits/main/slinfactory.c Tue Apr 8 23:23:11 2008
@@ -81,19 +81,20 @@
{
struct ast_frame *begin_frame = f, *duped_frame = NULL, *frame_ptr;
unsigned int x;
-
- if (f->subclass != AST_FORMAT_SLINEAR && f->subclass != AST_FORMAT_SLINEAR16) {
- if (sf->trans && f->subclass != sf->format) {
+ const struct ast_extended_codec slin16 = { .audio = { AST_FORMAT_AUDIO_SLINEAR16 } };
+
+ if (f->codec.audio[0] != AST_FORMAT_AUDIO_SLINEAR && f->codec.audio[0] != AST_FORMAT_AUDIO_SLINEAR16) {
+ if (sf->trans && !FMT_EQ(f->codec, sf->format)) {
ast_translator_free_path(sf->trans);
sf->trans = NULL;
}
if (!sf->trans) {
- if (!(sf->trans = ast_translator_build_path((f->subclass == AST_FORMAT_G722 ? AST_FORMAT_SLINEAR16 : AST_FORMAT_SLINEAR), f->subclass))) {
- ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f->subclass));
+ if (!(sf->trans = ast_translator_build_path((f->codec.audio[0] == AST_FORMAT_AUDIO_G722 ? slin16 : AST_FMT_SLINEAR), f->codec))) {
+ ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f->codec));
return 0;
}
- sf->format = f->subclass;
+ sf->format = f->codec;
}
if (!(begin_frame = ast_translate(sf->trans, f, 0)))
Modified: team/group/codec_bits/main/translate.c
URL: http://svn.digium.com/view/asterisk/team/group/codec_bits/main/translate.c?view=diff&rev=113646&r1=113645&r2=113646
==============================================================================
--- team/group/codec_bits/main/translate.c (original)
+++ team/group/codec_bits/main/translate.c Tue Apr 8 23:23:11 2008
@@ -55,31 +55,18 @@
* The full path can be reconstricted iterating on the matrix
* until step->dstfmt == desired_format.
*
- * Array indexes are 'src' and 'dest', in that order.
+ * Array indexes are 'src page', 'src bits', 'dest page', and 'dest bits', in that order.
*
* Note: the lock in the 'translators' list is also used to protect
* this structure.
*/
-static struct translator_path tr_matrix[MAX_FORMAT][MAX_FORMAT];
+static struct translator_path tr_matrix[sizeof(AST_FMT_NULL_MASK) / sizeof(AST_FMT_NULL_MASK.audio[0])][sizeof(AST_FMT_NULL_MASK.audio[0]) * 8][sizeof(AST_FMT_NULL_MASK) / sizeof(AST_FMT_NULL_MASK.audio[0])][sizeof(AST_FMT_NULL_MASK.audio[0]) * 8];
/*! \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.
*/
-
-/*! \brief returns the index of the lowest bit set */
-static force_inline int powerof(unsigned int d)
-{
- int x = ffs(d);
-
- if (x)
- return x - 1;
-
- ast_log(LOG_WARNING, "No bits set? %d\n", d);
-
- return -1;
-}
/*
* wrappers around the translator routines.
@@ -231,7 +218,7 @@
}
f->frametype = AST_FRAME_VOICE;
- f->subclass = 1 << (pvt->t->dstfmt);
+ f->codec = pvt->t->dstfmt;
f->mallocd = 0;
f->offset = AST_FRIENDLY_OFFSET;
f->src = pvt->t->name;
@@ -247,6 +234,27 @@
return ast_trans_frameout(pvt, 0, 0);
}
+static int page_and_bit_calculator(struct ast_extended_codec in, int *page, int *bits)
+{
+ union {
+ struct ast_extended_codec codec;
+ unsigned int bits[sizeof(struct ast_extended_codec) / sizeof(int)];
+ } _in = { in };
+ int ptmp, btmp;
+
+ for (ptmp = 0; ptmp < sizeof(struct ast_extended_codec) / sizeof(int); ptmp++) {
+ for (btmp = 0; btmp < sizeof(int) * 8; btmp++) {
+ if (_in.bits[ptmp] & (1 << (btmp))) {
+ *page = ptmp;
+ *bits = btmp;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
/* end of callback wrappers and helpers */
void ast_translator_free_path(struct ast_trans_pvt *p)
@@ -259,18 +267,26 @@
}
/*! \brief Build a chain of translators based upon the given source and dest formats */
-struct ast_trans_pvt *ast_translator_build_path(int dest, int source)
+struct ast_trans_pvt *ast_translator_build_path(struct ast_extended_codec dest, struct ast_extended_codec source)
{
struct ast_trans_pvt *head = NULL, *tail = NULL;
-
- source = powerof(source);
- dest = powerof(dest);
-
+ int dest_page, dest_bits, source_page, source_bits;
+
+ if (page_and_bit_calculator(dest, &dest_page, &dest_bits)) {
+ ast_log(LOG_ERROR, "Attempted to translate to NULL format\n");
+ return NULL;
+ }
+
+ if (page_and_bit_calculator(source, &source_page, &source_bits)) {
+ ast_log(LOG_ERROR, "Attempted to translate from NULL format\n");
+ return NULL;
+ }
+
AST_RWLIST_RDLOCK(&translators);
- while (source != dest) {
+ while (!FMT_EQ(source, dest)) {
struct ast_trans_pvt *cur;
- struct ast_translator *t = tr_matrix[source][dest].step;
+ struct ast_translator *t = tr_matrix[source_page][source_bits][dest_page][dest_bits].step;
if (!t) {
ast_log(LOG_WARNING, "No translator path from %s to %s\n",
ast_getformatname(source), ast_getformatname(dest));
@@ -278,9 +294,10 @@
return NULL;
}
if (!(cur = newpvt(t))) {
- ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
- if (head)
+ ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n", ast_getformatname(source), ast_getformatname(dest));
+ if (head) {
ast_translator_free_path(head);
+ }
AST_RWLIST_UNLOCK(&translators);
return NULL;
}
@@ -334,7 +351,7 @@
path->nextout = f->delivery;
}
/* Predict next incoming sample */
- path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(f->subclass)));
+ path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(f->codec)));
}
delivery = f->delivery;
for ( ; out && p ; p = p->next) {
@@ -358,7 +375,7 @@
/* Predict next outgoing timestamp from samples in this
frame. */
- path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->subclass)));
+ path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->codec)));
} else {
out->delivery = ast_tv(0, 0);
ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO);
@@ -440,28 +457,35 @@
static void rebuild_matrix(int samples)
{
struct ast_translator *t;
- int x; /* source format index */
- int y; /* intermediate format index */
- int z; /* destination format index */
+ union {
+ struct ast_extended_codec codec;
+ int bits[sizeof(struct ast_extended_codec) / sizeof(int)];
+ } x = { { { 0 } } }, y = { { { 0 } } }, z = { { { 0 } } };
+ int x_page, x_bits, y_page, y_bits, z_page, z_bits;
ast_debug(1, "Resetting translation matrix\n");
- bzero(tr_matrix, sizeof(tr_matrix));
+ memset(tr_matrix, 0, sizeof(tr_matrix));
/* first, compute all direct costs */
AST_RWLIST_TRAVERSE(&translators, t, list) {
if (!t->active)
continue;
- x = t->srcfmt;
- z = t->dstfmt;
-
- if (samples)
+ if (page_and_bit_calculator(t->srcfmt, &x_page, &x_bits)) {
+ continue;
+ }
+ if (page_and_bit_calculator(t->dstfmt, &z_page, &z_bits)) {
+ continue;
+ }
+
+ if (samples) {
calc_cost(t, samples);
+ }
- if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) {
- tr_matrix[x][z].step = t;
- tr_matrix[x][z].cost = t->cost;
+ if (!tr_matrix[x_page][x_bits][z_page][z_bits].step || t->cost < tr_matrix[x_page][x_bits][z_page][z_bits].cost) {
+ tr_matrix[x_page][x_bits][z_page][z_bits].step = t;
+ tr_matrix[x_page][x_bits][z_page][z_bits].cost = t->cost;
}
}
@@ -473,35 +497,55 @@
*/
for (;;) {
int changed = 0;
- for (x = 0; x < MAX_FORMAT; x++) { /* source format */
- for (y = 0; y < MAX_FORMAT; y++) { /* intermediate format */
- if (x == y) /* skip ourselves */
- continue;
-
- for (z = 0; z<MAX_FORMAT; z++) { /* dst format */
- int newcost;
-
- if (z == x || z == y) /* skip null conversions */
- continue;
- if (!tr_matrix[x][y].step) /* no path from x to y */
- continue;
- if (!tr_matrix[y][z].step) /* no path from y to z */
- continue;
- 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 */
- /* 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 */
+ for (x_page = 0; x_page < sizeof(struct ast_extended_codec) / sizeof(int); x_page++) {
+ for (x_bits = 0; x_bits < sizeof(int) * 8; x_bits++) {
+ x.bits[x_page] = 1 << x_bits;
+ for (y_page = 0; y_page < sizeof(struct ast_extended_codec) / sizeof(int); y_page++) {
+ for (y_bits = 0; y_bits < sizeof(int) * 8; y_bits++) {
+ if (x_page == y_page && x_bits == y_bits) {
+ /* Skip ourselves */
+ continue;
+ }
+ y.bits[y_page] = 1 << y_bits;
+ for (z_page = 0; z_page < sizeof(struct ast_extended_codec) / sizeof(int); z_page++) {
+ for (z_bits = 0; z_bits < sizeof(int) * 8; z_bits++) {
+ int newcost;
+ if ((z_page == x_page && z_bits == x_bits) || (z_page == y_page && z_bits == y_bits)) {
+ /* Skip null conversion */
+ continue;
+ }
+
+ if (!tr_matrix[x_page][x_bits][y_page][y_bits].step) { /* no path from x to y */
+ continue;
+ }
+ if (!tr_matrix[y_page][y_bits][z_page][z_bits].step) { /* no path from y to z */
+ continue;
+ }
+
+ newcost = tr_matrix[x_page][x_bits][y_page][y_bits].cost + tr_matrix[y_page][y_bits][z_page][z_bits].cost;
+
+ if (tr_matrix[x_page][x_bits][z_page][z_bits].step && newcost >= tr_matrix[x_page][x_bits][z_page][z_bits].cost) {
+ /* x->y->z is more expensive than the existing path */
+ 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;
- ast_debug(3, "Discovered %d cost path from %s to %s, via %d\n", tr_matrix[x][z].cost, ast_getformatname(x), ast_getformatname(z), y);
- changed++;
+ tr_matrix[x_page][x_bits][z_page][z_bits].step = tr_matrix[x_page][x_bits][y_page][y_bits].step;
+ tr_matrix[x_page][x_bits][z_page][z_bits].cost = newcost;
+ tr_matrix[x_page][x_bits][z_page][z_bits].multistep = 1;
+ z.bits[z_page] = 1 << z_bits;
+ ast_debug(3, "Discovered %d cost path from %s to %s, via %s\n", tr_matrix[x_page][x_bits][z_page][z_bits].cost, ast_getformatname(x.codec), ast_getformatname(z.codec), ast_getformatname(y.codec));
+ changed++;
+ }
+ z.bits[z_page] = 0;
+ }
+ }
+ y.bits[y_page] = 0;
}
}
+ x.bits[x_page] = 0;
}
if (!changed)
break;
@@ -510,9 +554,10 @@
static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
-#define SHOW_TRANS 16
- int x, y, z;
- int curlen = 0, longest = 0;
+ int curlen = 0, longest = 0, z;
+ struct ast_extended_codec source = AST_FMT_NULL_MASK_INIT, dest = AST_FMT_NULL_MASK_INIT, showme = AST_FMT_NULL_MASK_INIT;
+ int page, bits, d_page, d_bits;
+ struct ast_str *out = ast_str_alloca(200);
switch (cmd) {
case CLI_INIT:
@@ -543,7 +588,7 @@
ast_cli(a->fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
z = MAX_RECALC;
}
- ast_cli(a->fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
+ ast_cli(a->fd, " Recalculating Codec Translation (number of source seconds: %d)\n\n", z);
AST_RWLIST_WRLOCK(&translators);
rebuild_matrix(z);
AST_RWLIST_UNLOCK(&translators);
@@ -555,45 +600,93 @@
ast_cli(a->fd, " Translation times between formats (in microseconds) for one second of data\n");
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++) {
- curlen = strlen(ast_getformatname(1 << (x)));
- if (curlen > longest)
- longest = curlen;
- }
- for (x = -1; x < SHOW_TRANS; x++) {
- struct ast_str *out = ast_str_alloca(120);
- /*Go ahead and move to next iteration if dealing with an unknown codec*/
- if(x >= 0 && !strcmp(ast_getformatname(1 << (x)), "unknown"))
- continue;
- ast_str_set(&out, -1, " ");
- for (y = -1; y < SHOW_TRANS; y++) {
- /*Go ahead and move to next iteration if dealing with an unknown codec*/
- if (y >= 0 && !strcmp(ast_getformatname(1 << (y)), "unknown"))
+ for (page = 0; page < sizeof(showme.audio) / sizeof(showme.audio[0]); page++) {
+ for (bits = 0; bits < sizeof(showme.audio[0]) * 8; bits++) {
+ int found = 0;
+ source.audio[page] = 1 << bits;
+
+ /* Are there even translations for this codec? */
+ for (d_page = 0; d_page < sizeof(showme.audio) / sizeof(showme.audio[0]); d_page++) {
+ for (d_bits = 0; d_bits < sizeof(showme.audio[0]) * 8; d_bits++) {
+ struct ast_extended_codec dest = AST_FMT_NULL_MASK_INIT;
+ dest.audio[d_page] = 1 << d_bits;
+ if (tr_matrix[page][bits][d_page][d_bits].step) {
+ found = 1;
+ showme = FMT_OR(showme, dest);
+ curlen = strlen(ast_getformatname(source));
+ if (curlen > longest) {
+ longest = curlen;
+ }
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+ }
+ }
+ source.audio[page] = 0;
+ }
+
+ /* Top row */
+ for (d_page = 0; d_page < sizeof(showme.audio) / sizeof(showme.audio[0]); d_page++) {
+ for (d_bits = 0; d_bits < sizeof(showme.audio[0]) * 8; d_bits++) {
+ const char *name;
+ dest.audio[d_page] = 1 << d_bits;
+
+ /* Skip codecs without translations */
+ if (FMT_NOT(FMT_AND(dest, showme))) {
continue;
- if (y >= 0)
- curlen = strlen(ast_getformatname(1 << (y)));
- if (curlen < 5)
- curlen = 5;
- if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
- /* XXX 99999 is a little hackish
- We don't want this number being larger than the shortest (or current) codec
- For now, that is "gsm" */
- ast_str_append(&out, -1, "%*d", curlen + 1, tr_matrix[x][y].cost > 99999 ? 0 : tr_matrix[x][y].cost);
- } else if (x == -1 && y >= 0) {
- /* Top row - use a dynamic size */
- ast_str_append(&out, -1, "%*s", curlen + 1, ast_getformatname(1 << (y)) );
- } else if (y == -1 && x >= 0) {
- /* Left column - use a static size. */
- ast_str_append(&out, -1, "%*s", longest, ast_getformatname(1 << (x)) );
- } else if (x >= 0 && y >= 0) {
- ast_str_append(&out, -1, "%*s", curlen + 1, "-");
- } else {
- ast_str_append(&out, -1, "%*s", longest, "");
- }
- }
- ast_str_append(&out, -1, "\n");
- ast_cli(a->fd, "%s", out->str);
- }
+ }
+
+ name = ast_getformatname(dest);
+ ast_str_append(&out, 0, "%*s", (strlen(name) < 5 ? 5 : strlen(name)) + 1, name);
+ }
+ dest.audio[d_page] = 0;
+ }
+ ast_str_append(&out, 0, "\n");
+ ast_cli(a->fd, "%s", out->str);
+
+ for (page = 0; page < sizeof(showme.audio) / sizeof(showme.audio[0]); page++) {
+ for (bits = 0; bits < sizeof(showme.audio[0]) * 8; bits++) {
+ struct ast_str *out = ast_str_alloca(120);
+ source.audio[page] = 1 << bits;
+
+ ast_str_set(&out, 0, " %*s", longest, ast_getformatname(source));
+
+ for (d_page = 0; d_page < sizeof(showme.audio) / sizeof(showme.audio[0]); d_page++) {
+ for (d_bits = 0; d_bits < sizeof(showme.audio[0]) * 8; d_bits++) {
+ dest.audio[d_page] = 1 << d_bits;
+
+ /* Skip codecs without translations */
+ if (FMT_NOT(FMT_AND(dest, showme))) {
+ continue;
+ }
+ curlen = strlen(ast_getformatname(dest));
+
+ if (curlen < 5)
+ curlen = 5;
+
+ /* The only time this fails is for itself. */
+ if (tr_matrix[page][bits][d_page][d_bits].step) {
+ /* XXX 99999 is a little hackish
+ We don't want this number being larger than the shortest (or current) codec
+ For now, that is "gsm" */
+ ast_str_append(&out, 0, "%*d", curlen + 1,
+ tr_matrix[page][bits][d_page][d_bits].cost > 99999 ? 0 :
+ tr_matrix[page][bits][d_page][d_bits].cost);
+ } else {
+ ast_str_append(&out, -1, "%*s", curlen + 1, "-");
+ }
+ }
+ dest.audio[d_page] = 0;
+ }
+ ast_str_append(&out, -1, "\n");
+ ast_cli(a->fd, "%s", out->str);
+ }
+ source.audio[page] = 0;
+ }
+
AST_RWLIST_UNLOCK(&translators);
return CLI_SUCCESS;
}
@@ -621,8 +714,6 @@
t->module = mod;
- t->srcfmt = powerof(t->srcfmt);
- t->dstfmt = powerof(t->dstfmt);
t->active = 1;
if (t->plc_samples) {
@@ -631,18 +722,9 @@
t->plc_samples, t->buffer_samples);
return -1;
}
- if (t->dstfmt != powerof(AST_FORMAT_SLINEAR))
- ast_log(LOG_WARNING, "plc_samples %d format %x\n",
- t->plc_samples, t->dstfmt);
- }
- if (t->srcfmt >= MAX_FORMAT) {
- ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
- return -1;
- }
-
- if (t->dstfmt >= MAX_FORMAT) {
- ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
- return -1;
+ if (!FMT_EQ(t->dstfmt, AST_FMT_SLINEAR))
+ ast_log(LOG_WARNING, "plc_samples %d format %s\n",
+ t->plc_samples, ast_getformatname(t->dstfmt));
}
if (t->buf_size) {
@@ -663,7 +745,7 @@
ast_verb(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_getformatname(t->srcfmt), ast_getformatname(t->dstfmt), t->cost);
if (!added_cli) {
ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry));
@@ -675,8 +757,8 @@
/* find any existing translators that provide this same srcfmt/dstfmt,
and put this one in order based on cost */
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
- if ((u->srcfmt == t->srcfmt) &&
- (u->dstfmt == t->dstfmt) &&
+ if (FMT_EQ(u->srcfmt, t->srcfmt) &&
+ FMT_EQ(u->dstfmt, t->dstfmt) &&
(u->cost > t->cost)) {
AST_RWLIST_INSERT_BEFORE_CURRENT(t, list);
t = NULL;
@@ -707,7 +789,7 @@
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
if (u == t) {
AST_RWLIST_REMOVE_CURRENT(list);
- ast_verb(2, "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt));
+ ast_verb(2, "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(t->srcfmt), ast_getformatname(t->dstfmt));
found = 1;
break;
}
@@ -739,90 +821,123 @@
}
/*! \brief Calculate our best translator source format, given costs, and a desired destination */
-int ast_translator_best_choice(int *dst, int *srcs)
-{
- int x,y;
- int best = -1;
- int bestdst = 0;
- int cur, cursrc;
+int ast_translator_best_choice(struct ast_extended_codec *dst, struct ast_extended_codec *srcs)
+{
+ struct ast_extended_codec best = { { 0 } };
+ struct ast_extended_codec bestdst = { { 0 } };
int besttime = INT_MAX;
int beststeps = INT_MAX;
- int common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */
-
- if (common) { /* yes, pick one and return */
- for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
- if (cur & common) /* guaranteed to find one */
+ int page, bits;
+ int s_page, s_bits, d_page, d_bits;
+ union {
+ struct ast_extended_codec codec;
+ int bits[sizeof(struct ast_extended_codec) / sizeof(int)];
+ } common, d_test = { { { 0 } } }, s_test = { { { 0 } } };
+
+ common.codec = FMT_AND(AST_FMT_AUDIO_MASK, FMT_AND((*dst), (*srcs))); /* are there common formats ? */
+
+ if (FMT_NZ(common.codec)) { /* yes, pick one and return */
+ for (page = 0; page < sizeof(common.codec.audio) / sizeof(common.codec.audio[0]); page++) {
+ for (bits = 0; bits < sizeof(common.codec.audio[0]) * 8; bits++) {
+ if (common.codec.audio[page] & (1 << bits)) {
+ break;
+ }
+ }
+ if (common.codec.audio[page] & (1 << bits)) {
break;
+ }
}
/* We are done, this is a common format to both. */
- *srcs = *dst = cur;
+ common.codec = AST_FMT_NULL_MASK;
+ common.codec.audio[page] = 1 << bits;
+ *srcs = *dst = common.codec;
return 0;
} else { /* No, we will need to translate */
AST_RWLIST_RDLOCK(&translators);
- for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
- if (! (cur & *dst))
- continue;
- for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) {
- if (!(*srcs & cursrc) || !tr_matrix[x][y].step ||
- tr_matrix[x][y].cost > besttime)
- continue; /* not existing or no better */
- if (tr_matrix[x][y].cost < besttime ||
- tr_matrix[x][y].multistep < beststeps) {
- /* better than what we have so far */
- best = cursrc;
- bestdst = cur;
- besttime = tr_matrix[x][y].cost;
- beststeps = tr_matrix[x][y].multistep;
+ for (d_page = 0; d_page < sizeof(common.bits) / sizeof(common.bits[0]); d_page++) {
+ for (d_bits = 0; d_bits < sizeof(common.bits[0]) * 8; d_bits++) {
+ d_test.bits[d_page] = 1 << d_bits;
+ if (FMT_NOT(FMT_AND(d_test.codec, *dst))) {
+ continue;
}
- }
+
+ for (s_page = 0; s_page < sizeof(common.bits) / sizeof(common.bits[0]); s_page++) {
+ for (s_bits = 0; s_bits < sizeof(common.bits[0]) * 8; s_bits++) {
+ s_test.bits[s_page] = 1 << s_bits;
+
+ if (FMT_NOT(FMT_AND(*srcs, s_test.codec)) || !tr_matrix[s_page][s_bits][d_page][d_bits].step ||
+ tr_matrix[s_page][s_bits][d_page][d_bits].cost > besttime) {
+ continue; /* not existing or no better */
+ }
+
+ if (tr_matrix[s_page][s_bits][d_page][d_bits].cost < besttime ||
+ tr_matrix[s_page][s_bits][d_page][d_bits].multistep < beststeps) {
+ /* better than what we have so far */
+ best = s_test.codec;
+ bestdst = d_test.codec;
+ besttime = tr_matrix[s_page][s_bits][d_page][d_bits].cost;
+ beststeps = tr_matrix[s_page][s_bits][d_page][d_bits].multistep;
+ }
+ }
+ s_test.bits[s_page] = 0;
+ }
+ }
+ d_test.bits[d_page] = 0;
}
AST_RWLIST_UNLOCK(&translators);
- if (best > -1) {
+ if (FMT_NZ(best)) {
*srcs = best;
*dst = bestdst;
- best = 0;
- }
- return best;
- }
-}
-
-unsigned int ast_translate_path_steps(unsigned int dest, unsigned int src)
+ }
+ return FMT_NZ(best) ? 0 : -1;
+ }
+}
+
+unsigned int ast_translate_path_steps(struct ast_extended_codec dest, struct ast_extended_codec src)
{
unsigned int res = -1;
-
- /* convert bitwise format numbers into array indices */
- src = powerof(src);
- dest = powerof(dest);
+ int d_page, d_bits, s_page, s_bits;
+
+ if (page_and_bit_calculator(src, &s_page, &s_bits)) {
+ ast_log(LOG_ERROR, "Cannot translate from NULL codec\n");
+ return -1;
+ } else if (page_and_bit_calculator(dest, &d_page, &d_bits)) {
+ ast_log(LOG_ERROR, "Cannot translate to NULL codec\n");
+ return -1;
+ }
AST_RWLIST_RDLOCK(&translators);
- if (tr_matrix[src][dest].step)
- res = tr_matrix[src][dest].multistep + 1;
+ if (tr_matrix[s_page][s_bits][d_page][d_bits].step)
+ res = tr_matrix[s_page][s_bits][d_page][d_bits].multistep + 1;
AST_RWLIST_UNLOCK(&translators);
return res;
}
-unsigned int ast_translate_available_formats(unsigned int dest, unsigned int src)
-{
- unsigned int res = dest;
- unsigned int x;
- unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK;
- unsigned int src_video = src & AST_FORMAT_VIDEO_MASK;
+struct ast_extended_codec ast_translate_available_formats(struct ast_extended_codec dest, struct ast_extended_codec src)
+{
+ struct ast_extended_codec res = dest;
+ struct ast_extended_codec src_audio = FMT_AND(src, AST_FMT_AUDIO_MASK);
+ struct ast_extended_codec src_video = FMT_AND(src, AST_FMT_VIDEO_MASK);
+ int page, bits, a_page, a_bits, v_page, v_bits;
/* if we don't have a source format, we just have to try all
possible destination formats */
- if (!src)
+ if (FMT_NOT(src)) {
return dest;
-
- /* If we have a source audio format, get its format index */
- if (src_audio)
- src_audio = powerof(src_audio);
-
- /* If we have a source video format, get its format index */
- if (src_video)
- src_video = powerof(src_video);
+ }
+
+ if (page_and_bit_calculator(src_audio, &a_page, &a_bits)) {
+ ast_log(LOG_ERROR, "Cannot translate from NULL codec\n");
+ return AST_FMT_NULL_MASK;
+ }
+
+ if (page_and_bit_calculator(src_video, &v_page, &v_bits)) {
+ ast_log(LOG_ERROR, "Cannot translate to NULL codec\n");
+ return AST_FMT_NULL_MASK;
+ }
AST_RWLIST_RDLOCK(&translators);
@@ -830,52 +945,68 @@
known audio formats to determine whether there exists
a translation path from the source format to the
destination format. */
- for (x = 1; src_audio && (x & AST_FORMAT_AUDIO_MASK); x <<= 1) {
- /* if this is not a desired format, nothing to do */
- if (!dest & x)
- continue;
-
- /* if the source is supplying this format, then
- we can leave it in the result */
- if (src & x)
- continue;
-
- /* if we don't have a translation path from the src
- to this format, remove it from the result */
- if (!tr_matrix[src_audio][powerof(x)].step) {
- res &= ~x;
- continue;
- }
-
- /* now check the opposite direction */
- if (!tr_matrix[powerof(x)][src_audio].step)
- res &= ~x;
+ for (page = 0; page < sizeof(res.audio) / sizeof(res.audio[0]); page++) {
[... 85 lines stripped ...]
More information about the asterisk-commits
mailing list