[asterisk-commits] tilghman: branch tilghman/codec_bits2 r136849 - in /team/tilghman/codec_bits2...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Aug 8 14:37:56 CDT 2008
Author: tilghman
Date: Fri Aug 8 14:37:56 2008
New Revision: 136849
URL: http://svn.digium.com/view/asterisk?view=rev&rev=136849
Log:
More changes... ABI compat is a PITA
Modified:
team/tilghman/codec_bits2/include/asterisk/frame.h
team/tilghman/codec_bits2/include/asterisk/slinfactory.h
team/tilghman/codec_bits2/include/asterisk/translate.h
team/tilghman/codec_bits2/main/frame.c
team/tilghman/codec_bits2/main/slinfactory.c
team/tilghman/codec_bits2/main/translate.c
team/tilghman/codec_bits2/main/utils.c
Modified: team/tilghman/codec_bits2/include/asterisk/frame.h
URL: http://svn.digium.com/view/asterisk/team/tilghman/codec_bits2/include/asterisk/frame.h?view=diff&rev=136849&r1=136848&r2=136849
==============================================================================
--- team/tilghman/codec_bits2/include/asterisk/frame.h (original)
+++ team/tilghman/codec_bits2/include/asterisk/frame.h Fri Aug 8 14:37:56 2008
@@ -419,6 +419,7 @@
/*! \brief Definition of supported media formats (codecs) */
struct ast_format_list {
int bits; /*!< bitmask value */
+ struct ast_extended_codec ebits; /*!< more bitmasks */
char *name; /*!< short name */
int samplespersecond; /*!< Number of samples per second (8000/16000) */
char *desc; /*!< Description */
@@ -757,6 +758,40 @@
)
AST_INLINE_API(
+struct ast_extended_codec ast_extended_codec_and(struct ast_extended_codec format1, struct ast_extended_codec format2),
+{
+ int i;
+ int max = sizeof(format1) / sizeof(int);
+ union u {
+ struct ast_extended_codec c;
+ int bits[sizeof(format1) / sizeof(int)];
+ } u1 = { format1 };
+ union u u2 = { format2 };
+ for (i = 0; i < max; i++) {
+ u1.bits[i] = u1.bits[i] & u2.bits[i];
+ }
+ return u1.c;
+}
+)
+
+AST_INLINE_API(
+struct ast_extended_codec ast_extended_codec_or(struct ast_extended_codec format1, struct ast_extended_codec format2),
+{
+ int i;
+ int max = sizeof(format1) / sizeof(int);
+ union u {
+ struct ast_extended_codec c;
+ int bits[sizeof(format1) / sizeof(int)];
+ } u1 = { format1 };
+ union u u2 = { format2 };
+ for (i = 0; i < max; i++) {
+ u1.bits[i] = u1.bits[i] | u2.bits[i];
+ }
+ return u1.c;
+}
+)
+
+AST_INLINE_API(
int ast_extended_codec_equal(struct ast_extended_codec format1, struct ast_extended_codec format2),
{
return memcmp(&format1, &format2, sizeof(format1)) == 0 ? 1 : 0;
@@ -778,9 +813,6 @@
}
)
-extern struct ast_extended_codec ast_extended_codec_and(struct ast_extended_codec format1, struct ast_extended_codec format2);
-extern struct ast_extended_codec ast_extended_codec_or(struct ast_extended_codec format1, struct ast_extended_codec format2);
-
AST_INLINE_API(
int ast_extended_codec_isaudio(struct ast_extended_codec format),
{
Modified: team/tilghman/codec_bits2/include/asterisk/slinfactory.h
URL: http://svn.digium.com/view/asterisk/team/tilghman/codec_bits2/include/asterisk/slinfactory.h?view=diff&rev=136849&r1=136848&r2=136849
==============================================================================
--- team/tilghman/codec_bits2/include/asterisk/slinfactory.h (original)
+++ team/tilghman/codec_bits2/include/asterisk/slinfactory.h Fri Aug 8 14:37:56 2008
@@ -34,7 +34,7 @@
struct ast_slinfactory {
AST_LIST_HEAD_NOLOCK(, ast_frame) queue; /*!< A list of unaltered frames */
- struct ast_trans_pvt *trans; /*!< Translation path that converts fed frames into signed linear */
+ struct ast_trans2_pvt *trans; /*!< Translation path that converts fed frames into signed linear */
short hold[AST_SLINFACTORY_MAX_HOLD]; /*!< Hold for audio that no longer belongs to a frame (ie: if only some samples were taken from a frame) */
short *offset; /*!< Offset into the hold where audio begins */
size_t holdlen; /*!< Number of samples currently in the hold */
Modified: team/tilghman/codec_bits2/include/asterisk/translate.h
URL: http://svn.digium.com/view/asterisk/team/tilghman/codec_bits2/include/asterisk/translate.h?view=diff&rev=136849&r1=136848&r2=136849
==============================================================================
--- team/tilghman/codec_bits2/include/asterisk/translate.h (original)
+++ team/tilghman/codec_bits2/include/asterisk/translate.h Fri Aug 8 14:37:56 2008
@@ -39,6 +39,7 @@
#endif
struct ast_trans_pvt; /* declared below */
+struct ast_trans2_pvt; /* declared below */
/*! \brief
* Descriptor of a translator.
@@ -74,10 +75,6 @@
int srcfmt;
/*! Destination format (note: bit position, converted to index during registration) */
int dstfmt;
- /*! Extended source format (note: bit position, converted to index during registration) */
- struct ast_extended_codec esrcfmt;
- /*! Extended destination format (note: bit position, converted to index during registration) */
- struct ast_extended_codec edstfmt;
/*! initialize private data associated with the translator */
int (*newpvt)(struct ast_trans_pvt *);
@@ -125,16 +122,16 @@
struct ast_extended_codec edstfmt;
/*! initialize private data associated with the translator */
- int (*newpvt)(struct ast_trans_pvt *);
+ int (*newpvt)(struct ast_trans2_pvt *);
/*! Input frame callback. Store (and possibly convert) input frame. */
- int (*framein)(struct ast_trans_pvt *pvt, struct ast_frame *in);
+ int (*framein)(struct ast_trans2_pvt *pvt, struct ast_frame *in);
/*! Output frame callback. Generate a frame with outbuf content. */
- struct ast_frame * (*frameout)(struct ast_trans_pvt *pvt);
+ struct ast_frame * (*frameout)(struct ast_trans2_pvt *pvt);
/*! cleanup private data, if needed (often unnecessary). */
- void (*destroy)(struct ast_trans_pvt *pvt);
+ void (*destroy)(struct ast_trans2_pvt *pvt);
struct ast_frame * (*sample)(void); /*!< Generate an example frame */
@@ -159,8 +156,9 @@
int cost; /*!< Cost in milliseconds for encoding/decoding 1 second of sound */
int active; /*!< Whether this translator should be used or not */
- AST_LIST_ENTRY(ast_translator) list; /*!< link field */
+ AST_LIST_ENTRY(ast_translator2) list; /*!< link field */
struct ast_translator *legacy_registrant;
+ struct ast_trans_pvt *legacy_pvt;
};
/*! \brief
@@ -201,11 +199,31 @@
unsigned int destroy:1;
};
+struct ast_trans2_pvt {
+ struct ast_translator2 *t;
+ struct ast_frame f; /*!< used in frameout */
+ int samples; /*!< samples available in outbuf */
+ /*! \brief actual space used in outbuf */
+ int datalen;
+ void *pvt; /*!< more private data, if any */
+ union {
+ char *c; /*!< the useful portion of the buffer */
+ unsigned char *uc; /*!< the useful portion of the buffer */
+ int16_t *i16;
+ uint8_t *ui8;
+ } outbuf;
+ plc_state_t *plc; /*!< optional plc pointer */
+ struct ast_trans2_pvt *next; /*!< next in translator chain */
+ struct timeval nextin;
+ struct timeval nextout;
+ unsigned int destroy:1;
+};
+
/*! \brief generic frameout function */
struct ast_frame *ast_trans_frameout(struct ast_trans_pvt *pvt,
int datalen, int samples);
-
-struct ast_trans_pvt;
+struct ast_frame *ast_trans2_frameout(struct ast_trans2_pvt *pvt,
+ int datalen, int samples);
/*!
* \brief Register a translator
@@ -269,7 +287,7 @@
* \return ast_trans_pvt on success, NULL on failure
* */
struct ast_trans_pvt *ast_translator_build_path(int dest, int source);
-struct ast_trans_pvt *ast_translator2_build_path(struct ast_extended_codec dest, struct ast_extended_codec source);
+struct ast_trans2_pvt *ast_translator2_build_path(struct ast_extended_codec dest, struct ast_extended_codec source);
/*!
* \brief Frees a translator path
@@ -277,6 +295,7 @@
* \param tr translator path to get rid of
*/
void ast_translator_free_path(struct ast_trans_pvt *tr);
+void ast_translator2_free_path(struct ast_trans2_pvt *tr);
/*!
* \brief translates one or more frames
@@ -288,6 +307,7 @@
* \return an ast_frame of the new translation format on success, NULL on failure
*/
struct ast_frame *ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f, int consume);
+struct ast_frame *ast_translate2(struct ast_trans2_pvt *tr, struct ast_frame *f, int consume);
/*!
* \brief Returns the number of steps required to convert from 'src' to 'dest'.
Modified: team/tilghman/codec_bits2/main/frame.c
URL: http://svn.digium.com/view/asterisk/team/tilghman/codec_bits2/main/frame.c?view=diff&rev=136849&r1=136848&r2=136849
==============================================================================
--- team/tilghman/codec_bits2/main/frame.c (original)
+++ team/tilghman/codec_bits2/main/frame.c Fri Aug 8 14:37:56 2008
@@ -109,29 +109,34 @@
/*! \brief Definition of supported media formats (codecs) */
static struct ast_format_list AST_FORMAT_LIST[] = {
- { AST_FORMAT_G723_1 , "g723", 8000, "G.723.1", 20, 30, 300, 30, 30 }, /*!< G723.1 */
- { AST_FORMAT_GSM, "gsm", 8000, "GSM", 33, 20, 300, 20, 20 }, /*!< codec_gsm.c */
- { AST_FORMAT_ULAW, "ulaw", 8000, "G.711 u-law", 80, 10, 150, 10, 20 }, /*!< codec_ulaw.c */
- { AST_FORMAT_ALAW, "alaw", 8000, "G.711 A-law", 80, 10, 150, 10, 20 }, /*!< codec_alaw.c */
- { AST_FORMAT_G726, "g726", 8000, "G.726 RFC3551", 40, 10, 300, 10, 20 }, /*!< codec_g726.c */
- { AST_FORMAT_ADPCM, "adpcm" , 8000, "ADPCM", 40, 10, 300, 10, 20 }, /*!< codec_adpcm.c */
- { AST_FORMAT_SLINEAR, "slin", 8000, "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE }, /*!< Signed linear */
- { AST_FORMAT_LPC10, "lpc10", 8000, "LPC10", 7, 20, 20, 20, 20 }, /*!< codec_lpc10.c */
- { AST_FORMAT_G729A, "g729", 8000, "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 }, /*!< Binary commercial distribution */
- { AST_FORMAT_SPEEX, "speex", 8000, "SpeeX", 10, 10, 60, 10, 20 }, /*!< codec_speex.c */
- { AST_FORMAT_ILBC, "ilbc", 8000, "iLBC", 50, 30, 30, 30, 30 }, /*!< codec_ilbc.c */ /* inc=30ms - workaround */
- { AST_FORMAT_G726_AAL2, "g726aal2", 8000, "G.726 AAL2", 40, 10, 300, 10, 20 }, /*!< codec_g726.c */
- { AST_FORMAT_G722, "g722", 16000, "G722", 80, 10, 150, 10, 20 }, /*!< codec_g722.c */
- { AST_FORMAT_SLINEAR16, "slin16", 16000, "16 bit Signed Linear PCM (16kHz)", 320, 10, 70, 10, 20 }, /*!< Signed linear (16kHz) */
- { AST_FORMAT_JPEG, "jpeg", 0, "JPEG image"}, /*!< See format_jpeg.c */
- { AST_FORMAT_PNG, "png", 0, "PNG image"}, /*!< PNG Image format */
- { AST_FORMAT_H261, "h261", 0, "H.261 Video" }, /*!< H.261 Video Passthrough */
- { AST_FORMAT_H263, "h263", 0, "H.263 Video" }, /*!< H.263 Passthrough support, see format_h263.c */
- { AST_FORMAT_H263_PLUS, "h263p", 0, "H.263+ Video" }, /*!< H.263plus passthrough support See format_h263.c */
- { AST_FORMAT_H264, "h264", 0, "H.264 Video" }, /*!< Passthrough support, see format_h263.c */
- { AST_FORMAT_MP4_VIDEO, "mpeg4", 0, "MPEG4 Video" }, /*!< Passthrough support for MPEG4 */
- { AST_FORMAT_T140RED, "red", 1, "T.140 Realtime Text with redundancy"}, /*!< Redundant T.140 Realtime Text */
- { AST_FORMAT_T140, "t140", 0, "Passthrough T.140 Realtime Text" }, /*!< Passthrough support for T.140 Realtime Text */
+ { AST_FORMAT_G723_1, { .audio = { AST_FORMAT_G723_1 } }, "g723", 8000, "G.723.1", 20, 30, 300, 30, 30 }, /*!< G723.1 */
+ { AST_FORMAT_GSM, { .audio = { AST_FORMAT_GSM } }, "gsm", 8000, "GSM", 33, 20, 300, 20, 20 }, /*!< codec_gsm.c */
+ { AST_FORMAT_ULAW, { .audio = { AST_FORMAT_ULAW } }, "ulaw", 8000, "G.711 u-law", 80, 10, 150, 10, 20 }, /*!< codec_ulaw.c */
+ { AST_FORMAT_ALAW, { .audio = { AST_FORMAT_ALAW } }, "alaw", 8000, "G.711 A-law", 80, 10, 150, 10, 20 }, /*!< codec_alaw.c */
+ { AST_FORMAT_G726, { .audio = { AST_FORMAT_G726 } }, "g726", 8000, "G.726 RFC3551", 40, 10, 300, 10, 20 }, /*!< codec_g726.c */
+ { AST_FORMAT_ADPCM, { .audio = { AST_FORMAT_ADPCM } }, "adpcm" , 8000, "ADPCM", 40, 10, 300, 10, 20 }, /*!< codec_adpcm.c */
+ { AST_FORMAT_SLINEAR, { .audio = { AST_FORMAT_SLINEAR } }, "slin", 8000, "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE },
+ /*!< Signed linear */
+ { AST_FORMAT_LPC10, { .audio = { AST_FORMAT_LPC10 } }, "lpc10", 8000, "LPC10", 7, 20, 20, 20, 20 }, /*!< codec_lpc10.c */
+ { AST_FORMAT_G729A, { .audio = { AST_FORMAT_G729A } }, "g729", 8000, "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 },
+ /*!< Binary commercial distribution */
+ { AST_FORMAT_SPEEX, { .audio = { AST_FORMAT_SPEEX } }, "speex", 8000, "SpeeX", 10, 10, 60, 10, 20 }, /*!< codec_speex.c */
+ { AST_FORMAT_ILBC, { .audio = { AST_FORMAT_ILBC } }, "ilbc", 8000, "iLBC", 50, 30, 30, 30, 30 }, /*!< codec_ilbc.c */ /* inc=30ms - workaround */
+ { AST_FORMAT_G726_AAL2, { .audio = { AST_FORMAT_G726_AAL2 } }, "g726aal2", 8000, "G.726 AAL2", 40, 10, 300, 10, 20 },
+ /*!< codec_g726.c */
+ { AST_FORMAT_G722, { .audio = { AST_FORMAT_G722 } }, "g722", 16000, "G722", 80, 10, 150, 10, 20 }, /*!< codec_g722.c */
+ { AST_FORMAT_SLINEAR16, { .audio = { AST_FORMAT_SLINEAR16 } }, "slin16", 16000, "16 bit Signed Linear PCM (16kHz)", 320, 10, 70, 10, 20 },
+ /*!< Signed linear (16kHz) */
+ { AST_FORMAT_JPEG, { .audio = { AST_FORMAT_JPEG } }, "jpeg", 0, "JPEG image"}, /*!< See format_jpeg.c */
+ { AST_FORMAT_PNG, { .audio = { AST_FORMAT_PNG } }, "png", 0, "PNG image"}, /*!< PNG Image format */
+ { AST_FORMAT_H261, { .audio = { AST_FORMAT_H261 } }, "h261", 0, "H.261 Video" }, /*!< H.261 Video Passthrough */
+ { AST_FORMAT_H263, { .audio = { AST_FORMAT_H263 } }, "h263", 0, "H.263 Video" }, /*!< H.263 Passthrough support, see format_h263.c */
+ { AST_FORMAT_H263_PLUS, { .audio = { AST_FORMAT_H263_PLUS } }, "h263p", 0, "H.263+ Video" }, /*!< H.263plus passthrough support See format_h263.c */
+ { AST_FORMAT_H264, { .audio = { AST_FORMAT_H264 } }, "h264", 0, "H.264 Video" }, /*!< Passthrough support, see format_h263.c */
+ { AST_FORMAT_MP4_VIDEO, { .audio = { AST_FORMAT_MP4_VIDEO } }, "mpeg4", 0, "MPEG4 Video" }, /*!< Passthrough support for MPEG4 */
+ { AST_FORMAT_T140RED, { .audio = { AST_FORMAT_T140RED } }, "red", 1, "T.140 Realtime Text with redundancy" },
+ /*!< Redundant T.140 Realtime Text */
+ { AST_FORMAT_T140, { .audio = { AST_FORMAT_T140 } }, "t140", 0, "Passthrough T.140 Realtime Text" }, /*!< Passthrough support for T.140 Realtime Text */
};
struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
@@ -559,6 +564,46 @@
return buf;
}
+char *ast_geteformatname(struct ast_extended_codec format)
+{
+ int x;
+ char *ret = "unknown";
+ for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
+ if (FMT_EQ(AST_FORMAT_LIST[x].ebits, format)) {
+ ret = AST_FORMAT_LIST[x].name;
+ break;
+ }
+ }
+ return ret;
+}
+
+char *ast_geteformatname_multiple(char *buf, size_t size, struct ast_extended_codec format)
+{
+ int x;
+ unsigned len;
+ char *start, *end = buf;
+
+ if (!size) {
+ return buf;
+ }
+ len = strlen(end);
+ end += len;
+ size -= len;
+ start = end;
+ for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
+ if (FMT_NZ(FMT_AND(AST_FORMAT_LIST[x].ebits, format))) {
+ len = snprintf(end, size, "%s|", AST_FORMAT_LIST[x].name);
+ end += len;
+ size -= len;
+ }
+ }
+ if (start == end)
+ ast_copy_string(start, "nothing", size);
+ else if (size > 1)
+ *(end -1) = '\0';
+ return buf;
+}
+
static struct ast_codec_alias_table {
char *alias;
char *realname;
Modified: team/tilghman/codec_bits2/main/slinfactory.c
URL: http://svn.digium.com/view/asterisk/team/tilghman/codec_bits2/main/slinfactory.c?view=diff&rev=136849&r1=136848&r2=136849
==============================================================================
--- team/tilghman/codec_bits2/main/slinfactory.c (original)
+++ team/tilghman/codec_bits2/main/slinfactory.c Fri Aug 8 14:37:56 2008
@@ -61,7 +61,7 @@
struct ast_frame *f;
if (sf->trans) {
- ast_translator_free_path(sf->trans);
+ ast_translator2_free_path(sf->trans);
sf->trans = NULL;
}
@@ -87,7 +87,7 @@
f->codec.audio[0] != AST_FORMAT_SLINEAR &&
f->codec.audio[0] != AST_FORMAT_SLINEAR16)) {
if (sf->trans && (f->subclass != sf->format || (f->subclass == AST_FORMAT_EXTENDED && !FMT_EQ(f->codec, sf->eformat)))) {
- ast_translator_free_path(sf->trans);
+ ast_translator2_free_path(sf->trans);
sf->trans = NULL;
}
@@ -96,16 +96,16 @@
!(sf->trans = ast_translator2_build_path(
(ast_eformat_rate(f->codec) > 8000) ? AST_FMT_SLINEAR16 : AST_FMT_SLINEAR, f->codec))) ||
(f->subclass != AST_FORMAT_EXTENDED &&
- !(sf->trans = ast_translator_build_path(
- (ast_format_rate(f->subclass) > 8000 ? 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));
+ !(sf->trans = ast_translator2_build_path(
+ (ast_format_rate(f->subclass) > 8000 ? AST_FMT_SLINEAR16 : AST_FMT_SLINEAR), ast_codec2extended(f->subclass))))) {
+ ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", f->subclass == AST_FORMAT_EXTENDED ? ast_geteformatname(f->codec) : ast_getformatname(f->subclass));
return 0;
}
sf->format = f->subclass;
sf->eformat = f->codec;
}
- if (!(begin_frame = ast_translate(sf->trans, f, 0)))
+ if (!(begin_frame = ast_translate2(sf->trans, f, 0)))
return 0;
duped_frame = ast_frdup(begin_frame);
@@ -116,7 +116,7 @@
return 0;
} else {
if (sf->trans) {
- ast_translator_free_path(sf->trans);
+ ast_translator2_free_path(sf->trans);
sf->trans = NULL;
}
if (!(duped_frame = ast_frdup(f)))
@@ -221,7 +221,7 @@
struct ast_frame *fr = NULL;
if (sf->trans) {
- ast_translator_free_path(sf->trans);
+ ast_translator2_free_path(sf->trans);
sf->trans = NULL;
}
Modified: team/tilghman/codec_bits2/main/translate.c
URL: http://svn.digium.com/view/asterisk/team/tilghman/codec_bits2/main/translate.c?view=diff&rev=136849&r1=136848&r2=136849
==============================================================================
--- team/tilghman/codec_bits2/main/translate.c (original)
+++ team/tilghman/codec_bits2/main/translate.c Fri Aug 8 14:37:56 2008
@@ -89,7 +89,7 @@
* \brief Allocate the descriptor, required outbuf space,
* and possibly also plc and desc.
*/
-static void *newpvt(struct ast_translator2 *t)
+static void *newpvt(struct ast_translator *t)
{
struct ast_trans_pvt *pvt;
int len;
@@ -129,6 +129,49 @@
return pvt;
}
+static void *newpvt2(struct ast_translator2 *t)
+{
+ struct ast_trans2_pvt *pvt;
+ int len;
+ int useplc = t->plc_samples > 0 && t->useplc; /* cache, because it can change on the fly */
+ char *ofs;
+
+ /*
+ * compute the required size adding private descriptor,
+ * plc, buffer, AST_FRIENDLY_OFFSET.
+ */
+ len = sizeof(*pvt) + t->desc_size;
+ if (useplc)
+ len += sizeof(plc_state_t);
+ if (t->buf_size)
+ len += AST_FRIENDLY_OFFSET + t->buf_size;
+ pvt = ast_calloc(1, len);
+ if (!pvt)
+ return NULL;
+ pvt->t = t;
+ ofs = (char *)(pvt + 1); /* pointer to data space */
+ if (t->desc_size) { /* first comes the descriptor */
+ pvt->pvt = ofs;
+ ofs += t->desc_size;
+ }
+ if (useplc) { /* then plc state */
+ pvt->plc = (plc_state_t *)ofs;
+ ofs += sizeof(plc_state_t);
+ }
+ if (t->buf_size) /* finally buffer and header */
+ pvt->outbuf.c = ofs + AST_FRIENDLY_OFFSET;
+ /* call local init routine, if present */
+ if (t->newpvt && t->newpvt(pvt)) {
+ ast_free(pvt);
+ return NULL;
+ } else if (t->legacy_registrant) {
+ t->legacy_pvt = newpvt(t->legacy_registrant);
+ }
+
+ ast_module_ref(t->module);
+ return pvt;
+}
+
static void destroy(struct ast_trans_pvt *pvt)
{
struct ast_translator *t = pvt->t;
@@ -146,6 +189,33 @@
if (t->destroy)
t->destroy(pvt);
+ ast_free(pvt);
+ ast_module_unref(t->module);
+}
+
+static void destroy2(struct ast_trans2_pvt *pvt)
+{
+ struct ast_translator2 *t = pvt->t;
+
+ if (ast_test_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR)) {
+ /* If this flag is still set, that means that the translation path has
+ * been torn down, while we still have a frame out there being used.
+ * When ast_frfree() gets called on that frame, this ast_trans_pvt
+ * will get destroyed, too. */
+
+ pvt->destroy = 1;
+
+ return;
+ }
+
+ if (t->destroy)
+ t->destroy(pvt);
+ if (t->legacy_pvt) {
+ t->legacy_registrant->destroy(t->legacy_pvt);
+ ast_free(t->legacy_pvt);
+ t->legacy_pvt = NULL;
+ }
+
ast_free(pvt);
ast_module_unref(t->module);
}
@@ -205,6 +275,64 @@
return ret;
}
+static int framein2(struct ast_trans2_pvt *pvt, struct ast_frame *f)
+{
+ int16_t *dst = pvt->outbuf.i16;
+ int ret;
+ int samples = pvt->samples; /* initial value */
+
+ if (pvt->t->legacy_pvt) {
+ return framein(pvt->t->legacy_pvt, f);
+ }
+
+ /* Copy the last in jb timing info to the pvt */
+ ast_copy_flags(&pvt->f, f, AST_FRFLAG_HAS_TIMING_INFO);
+ pvt->f.ts = f->ts;
+ pvt->f.len = f->len;
+ pvt->f.seqno = f->seqno;
+
+ if (f->samples == 0) {
+ ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
+ }
+ if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */
+ if (f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
+ if (pvt->plc) {
+ int l = pvt->t->plc_samples;
+ if (pvt->samples + l > pvt->t->buffer_samples) {
+ ast_log(LOG_WARNING, "Out of buffer space\n");
+ return -1;
+ }
+ l = plc_fillin(pvt->plc, dst + pvt->samples, l);
+ pvt->samples += l;
+ pvt->datalen = pvt->samples * 2; /* SLIN has 2bytes for 1sample */
+ }
+ /* We don't want generic PLC. If the codec has native PLC, then do that */
+ if (!pvt->t->native_plc)
+ return 0;
+ }
+ if (pvt->samples + f->samples > pvt->t->buffer_samples) {
+ ast_log(LOG_WARNING, "Out of buffer space\n");
+ return -1;
+ }
+ }
+ /* we require a framein routine, wouldn't know how to do
+ * it otherwise.
+ */
+ ret = pvt->t->framein(pvt, f);
+ /* possibly store data for plc */
+ if (!ret && pvt->plc) {
+ int l = pvt->t->plc_samples;
+ if (pvt->samples < l)
+ l = pvt->samples;
+ plc_rx(pvt->plc, dst + pvt->samples - l, l);
+ }
+ /* diagnostic ... */
+ if (pvt->samples == samples)
+ ast_log(LOG_WARNING, "%s did not update samples %d\n",
+ pvt->t->name, pvt->samples);
+ return ret;
+}
+
/*! \brief generic frameout routine.
* If samples and datalen are 0, take whatever is in pvt
* and reset them, otherwise take the values in the caller and
@@ -242,9 +370,50 @@
return f;
}
+static struct ast_frame *default_frameout(struct ast_trans_pvt *pvt) attribute_unused;
static struct ast_frame *default_frameout(struct ast_trans_pvt *pvt)
{
return ast_trans_frameout(pvt, 0, 0);
+}
+
+struct ast_frame *ast_trans2_frameout(struct ast_trans2_pvt *pvt,
+ int datalen, int samples)
+{
+ struct ast_frame *f = &pvt->f;
+
+ if (samples)
+ f->samples = samples;
+ else {
+ if (pvt->samples == 0)
+ return NULL;
+ f->samples = pvt->samples;
+ pvt->samples = 0;
+ }
+ if (datalen)
+ f->datalen = datalen;
+ else {
+ f->datalen = pvt->datalen;
+ pvt->datalen = 0;
+ }
+
+ f->frametype = AST_FRAME_VOICE;
+ if (!(f->subclass = ast_extended2codec(pvt->t->edstfmt))) {
+ f->subclass = AST_FORMAT_EXTENDED;
+ f->codec = pvt->t->edstfmt;
+ }
+ f->mallocd = 0;
+ f->offset = AST_FRIENDLY_OFFSET;
+ f->src = pvt->t->name;
+ f->data.ptr = pvt->outbuf.c;
+
+ ast_set_flag(f, AST_FRFLAG_FROM_TRANSLATOR);
+
+ return f;
+}
+
+static struct ast_frame *default_frameout2(struct ast_trans2_pvt *pvt)
+{
+ return ast_trans2_frameout(pvt, 0, 0);
}
/* end of callback wrappers and helpers */
@@ -255,6 +424,15 @@
while ( (p = pn) ) {
pn = p->next;
destroy(p);
+ }
+}
+
+void ast_translator2_free_path(struct ast_trans2_pvt *p)
+{
+ struct ast_trans2_pvt *pn = p;
+ while ( (p = pn) ) {
+ pn = p->next;
+ destroy2(p);
}
}
@@ -280,9 +458,9 @@
}
/*! \brief Build a chain of translators based upon the given source and dest formats */
-struct ast_trans_pvt *ast_translator2_build_path(struct ast_extended_codec dest, struct ast_extended_codec source)
-{
- struct ast_trans_pvt *head = NULL, *tail = NULL;
+struct ast_trans2_pvt *ast_translator2_build_path(struct ast_extended_codec dest, struct ast_extended_codec source)
+{
+ struct ast_trans2_pvt *head = NULL, *tail = NULL;
int dest_page, dest_bits, source_page, source_bits;
if (page_and_bit_calculator(dest, &dest_page, &dest_bits)) {
@@ -298,7 +476,7 @@
AST_RWLIST_RDLOCK(&translators);
while (!FMT_EQ(source, dest)) {
- struct ast_trans_pvt *cur;
+ struct ast_trans2_pvt *cur;
struct ast_translator2 *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",
@@ -306,10 +484,10 @@
AST_RWLIST_UNLOCK(&translators);
return NULL;
}
- if (!(cur = newpvt(t))) {
+ if (!(cur = newpvt2(t))) {
ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n", ast_geteformatname(source), ast_geteformatname(dest));
if (head)
- ast_translator_free_path(head);
+ ast_translator2_free_path(head);
AST_RWLIST_UNLOCK(&translators);
return NULL;
}
@@ -329,7 +507,8 @@
struct ast_trans_pvt *ast_translator_build_path(int dest, int source)
{
- return ast_translator2_build_path(ast_codec2extended(dest), ast_codec2extended(source));
+ ast_log(LOG_ERROR, "ast_translator_build_path() is no longer functional in this version\n");
+ return NULL;
}
/*! \brief do the actual translation */
@@ -408,11 +587,86 @@
return out;
}
+struct ast_frame *ast_translate2(struct ast_trans2_pvt *path, struct ast_frame *f, int consume)
+{
+ struct ast_trans2_pvt *p = path;
+ struct ast_frame *out = f;
+ struct timeval delivery;
+ int has_timing_info;
+ long ts;
+ long len;
+ int seqno;
+
+ has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO);
+ ts = f->ts;
+ len = f->len;
+ seqno = f->seqno;
+
+ /* XXX hmmm... check this below */
+ if (!ast_tvzero(f->delivery)) {
+ if (!ast_tvzero(path->nextin)) {
+ /* Make sure this is in line with what we were expecting */
+ if (!ast_tveq(path->nextin, f->delivery)) {
+ /* The time has changed between what we expected and this
+ most recent time on the new packet. If we have a
+ valid prediction adjust our output time appropriately */
+ if (!ast_tvzero(path->nextout)) {
+ path->nextout = ast_tvadd(path->nextout,
+ ast_tvsub(f->delivery, path->nextin));
+ }
+ path->nextin = f->delivery;
+ }
+ } else {
+ /* This is our first pass. Make sure the timing looks good */
+ path->nextin = f->delivery;
+ path->nextout = f->delivery;
+ }
+ /* Predict next incoming sample */
+ path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(f->subclass)));
+ }
+ delivery = f->delivery;
+ for ( ; out && p ; p = p->next) {
+ framein2(p, out);
+ if (out != f)
+ ast_frfree(out);
+ out = p->t->frameout(p);
+ }
+ if (consume)
+ ast_frfree(f);
+ if (out == NULL)
+ return NULL;
+ /* we have a frame, play with times */
+ if (!ast_tvzero(delivery)) {
+ /* Regenerate prediction after a discontinuity */
+ if (ast_tvzero(path->nextout))
+ path->nextout = ast_tvnow();
+
+ /* Use next predicted outgoing timestamp */
+ out->delivery = path->nextout;
+
+ /* Predict next outgoing timestamp from samples in this
+ frame. */
+ path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->subclass)));
+ } else {
+ out->delivery = ast_tv(0, 0);
+ ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO);
+ if (has_timing_info) {
+ out->ts = ts;
+ out->len = len;
+ out->seqno = seqno;
+ }
+ }
+ /* Invalidate prediction if we're entering a silence period */
+ if (out->frametype == AST_FRAME_CNG)
+ path->nextout = ast_tv(0, 0);
+ return out;
+}
+
/*! \brief compute the cost of a single translation step */
static void calc_cost(struct ast_translator2 *t, int seconds)
{
int num_samples = 0;
- struct ast_trans_pvt *pvt;
+ struct ast_trans2_pvt *pvt;
struct rusage start;
struct rusage end;
int cost;
@@ -428,7 +682,7 @@
return;
}
- pvt = newpvt(t);
+ pvt = newpvt2(t);
if (!pvt) {
ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
t->cost = 999999;
@@ -442,11 +696,11 @@
struct ast_frame *f = t->sample();
if (!f) {
ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
- destroy(pvt);
+ destroy2(pvt);
t->cost = 999999;
return;
}
- framein(pvt, f);
+ framein2(pvt, f);
ast_frfree(f);
while ((f = t->frameout(pvt))) {
num_samples += f->samples;
@@ -459,7 +713,7 @@
cost = ((end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000) + end.ru_utime.tv_usec - start.ru_utime.tv_usec;
cost += ((end.ru_stime.tv_sec - start.ru_stime.tv_sec) * 1000000) + end.ru_stime.tv_usec - start.ru_stime.tv_usec;
- destroy(pvt);
+ destroy2(pvt);
t->cost = cost / seconds;
@@ -766,7 +1020,7 @@
}
if (t->frameout == NULL)
- t->frameout = default_frameout;
+ t->frameout = default_frameout2;
calc_cost(t, 1);
@@ -807,7 +1061,7 @@
int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
{
- struct ast_translator2 *t2 = ast_calloc(1, sizeof(*t2) + sizeof(struct ast_translator *));
+ struct ast_translator2 *t2 = ast_calloc(1, sizeof(*t2));
if (!t2) {
return -1;
}
@@ -815,11 +1069,15 @@
ast_copy_string((char *)t2->name, t->name, sizeof(t2->name));
t2->esrcfmt = ast_codec2extended(t->srcfmt);
t2->edstfmt = ast_codec2extended(t->dstfmt);
- /* After the first three fields, the memory structures are identical */
- memcpy(t2 + sizeof(t2->name) + sizeof(t2->esrcfmt) + sizeof(t2->edstfmt),
- t + sizeof(t->name) + sizeof(t->srcfmt) + sizeof(t->dstfmt),
- sizeof(t2) - sizeof(t2->name) - sizeof(t2->esrcfmt) - sizeof(t2->edstfmt) - sizeof(t2->legacy_registrant));
+ t2->sample = t->sample;
+ t2->buffer_samples = t->buffer_samples;
+ t2->buf_size = t->buf_size;
+ t2->desc_size = t->desc_size;
+ t2->plc_samples = t->plc_samples;
+ t2->useplc = t->useplc;
+ t2->native_plc = t->native_plc;
t2->legacy_registrant = t;
+ t->module = mod;
return __ast_register_translator2(t2, mod);
}
@@ -859,7 +1117,7 @@
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
if (u->legacy_registrant == 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_geteformatname(t->esrcfmt), ast_geteformatname(t->edstfmt));
+ 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));
break;
}
}
Modified: team/tilghman/codec_bits2/main/utils.c
URL: http://svn.digium.com/view/asterisk/team/tilghman/codec_bits2/main/utils.c?view=diff&rev=136849&r1=136848&r2=136849
==============================================================================
--- team/tilghman/codec_bits2/main/utils.c (original)
+++ team/tilghman/codec_bits2/main/utils.c Fri Aug 8 14:37:56 2008
@@ -61,6 +61,9 @@
#define AST_API_MODULE
#include "asterisk/config.h"
+
+#define AST_API_MODULE
+#include "asterisk/frame.h"
static char base64[64];
static char b2a[256];
More information about the asterisk-commits
mailing list