[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