[asterisk-commits] file: branch group/media_formats r406018 - in /team/group/media_formats: incl...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jan 21 10:34:46 CST 2014


Author: file
Date: Tue Jan 21 10:34:38 2014
New Revision: 406018

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=406018
Log:
Move stuff around to more logical locations.

Added:
    team/group/media_formats/include/asterisk/smoother.h   (with props)
    team/group/media_formats/main/smoother.c   (with props)
Modified:
    team/group/media_formats/include/asterisk/format.h
    team/group/media_formats/include/asterisk/frame.h
    team/group/media_formats/main/format.c
    team/group/media_formats/main/frame.c
    team/group/media_formats/res/res_fax.c
    team/group/media_formats/res/res_rtp_asterisk.c

Modified: team/group/media_formats/include/asterisk/format.h
URL: http://svnview.digium.com/svn/asterisk/team/group/media_formats/include/asterisk/format.h?view=diff&rev=406018&r1=406017&r2=406018
==============================================================================
--- team/group/media_formats/include/asterisk/format.h (original)
+++ team/group/media_formats/include/asterisk/format.h Tue Jan 21 10:34:38 2014
@@ -30,6 +30,10 @@
 #include "asterisk/silk.h"
 #include "asterisk/celt.h"
 #include "asterisk/opus.h"
+
+struct ast_format_cap;
+struct ast_codec_pref;
+
 #define AST_FORMAT_ATTR_SIZE 64
 #define AST_FORMAT_INC 100000
 
@@ -451,6 +455,18 @@
  */
 int ast_format_rate(const struct ast_format *format);
 
+/*! \brief Returns the number of samples contained in the frame */
+int ast_codec_get_samples(struct ast_frame *f);
+
+/*! \brief Returns the number of bytes for the number of samples of the given format */
+int ast_codec_get_len(struct ast_format *format, int samples);
+
+/*! \brief Gets duration in ms of interpolation frame for a format */
+static inline int ast_codec_interp_len(struct ast_format *format)
+{
+	return (format->id == AST_FORMAT_ILBC) ? 30 : 20;
+}
+
 /*!
  * \brief register ast_format_attr_interface with core.
  *
@@ -477,6 +493,13 @@
  */
 enum ast_format_id ast_format_slin_by_rate(unsigned int rate);
 
+/*! \brief Parse an "allow" or "deny" line in a channel or device configuration
+	and update the capabilities and pref if provided.
+	Video codecs are not added to codec preference lists, since we can not transcode
+	\return Returns number of errors encountered during parsing
+ */
+int ast_parse_allow_disallow(struct ast_codec_pref *pref, struct ast_format_cap *cap, const char *list, int allowing);
+
 /*!
  * \since 12
  * \brief Get the message type used for signaling a format registration

Modified: team/group/media_formats/include/asterisk/frame.h
URL: http://svnview.digium.com/svn/asterisk/team/group/media_formats/include/asterisk/frame.h?view=diff&rev=406018&r1=406017&r2=406018
==============================================================================
--- team/group/media_formats/include/asterisk/frame.h (original)
+++ team/group/media_formats/include/asterisk/frame.h Tue Jan 21 10:34:38 2014
@@ -352,9 +352,6 @@
 	char code[1];				/*!< Tech-specific cause code information, beginning with the name of the tech */
 };
 
-#define AST_SMOOTHER_FLAG_G729		(1 << 0)
-#define AST_SMOOTHER_FLAG_BE		(1 << 1)
-
 /* Option identifiers and flags */
 #define AST_OPTION_FLAG_REQUEST		0
 #define AST_OPTION_FLAG_ACCEPT		1
@@ -533,76 +530,10 @@
 #define ast_frame_byteswap_be(fr) do { ; } while(0)
 #endif
 
-/*! \brief Parse an "allow" or "deny" line in a channel or device configuration
-	and update the capabilities and pref if provided.
-	Video codecs are not added to codec preference lists, since we can not transcode
-	\return Returns number of errors encountered during parsing
- */
-int ast_parse_allow_disallow(struct ast_codec_pref *pref, struct ast_format_cap *cap, const char *list, int allowing);
-
-/*! \name AST_Smoother
-*/
-/*@{ */
-/*! \page ast_smooth The AST Frame Smoother
-The ast_smoother interface was designed specifically
-to take frames of variant sizes and produce frames of a single expected
-size, precisely what you want to do.
-
-The basic interface is:
-
-- Initialize with ast_smoother_new()
-- Queue input frames with ast_smoother_feed()
-- Get output frames with ast_smoother_read()
-- when you're done, free the structure with ast_smoother_free()
-- Also see ast_smoother_test_flag(), ast_smoother_set_flags(), ast_smoother_get_flags(), ast_smoother_reset()
-*/
-struct ast_smoother;
-
-struct ast_smoother *ast_smoother_new(int bytes);
-void ast_smoother_set_flags(struct ast_smoother *smoother, int flags);
-int ast_smoother_get_flags(struct ast_smoother *smoother);
-int ast_smoother_test_flag(struct ast_smoother *s, int flag);
-void ast_smoother_free(struct ast_smoother *s);
-void ast_smoother_reset(struct ast_smoother *s, int bytes);
-
-/*!
- * \brief Reconfigure an existing smoother to output a different number of bytes per frame
- * \param s the smoother to reconfigure
- * \param bytes the desired number of bytes per output frame
- * \return nothing
- *
- */
-void ast_smoother_reconfigure(struct ast_smoother *s, int bytes);
-
-int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap);
-struct ast_frame *ast_smoother_read(struct ast_smoother *s);
-#define ast_smoother_feed(s,f) __ast_smoother_feed(s, f, 0)
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 1)
-#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 0)
-#else
-#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 0)
-#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 1)
-#endif
-/*@} Doxygen marker */
-
 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix);
-
-/*! \brief Returns the number of samples contained in the frame */
-int ast_codec_get_samples(struct ast_frame *f);
-
-/*! \brief Returns the number of bytes for the number of samples of the given format */
-int ast_codec_get_len(struct ast_format *format, int samples);
 
 /*! \brief Appends a frame to the end of a list of frames, truncating the maximum length of the list */
 struct ast_frame *ast_frame_enqueue(struct ast_frame *head, struct ast_frame *f, int maxlen, int dupe);
-
-
-/*! \brief Gets duration in ms of interpolation frame for a format */
-static inline int ast_codec_interp_len(struct ast_format *format)
-{
-	return (format->id == AST_FORMAT_ILBC) ? 30 : 20;
-}
 
 /*!
   \brief Adjusts the volume of the audio samples contained in a frame.

Added: team/group/media_formats/include/asterisk/smoother.h
URL: http://svnview.digium.com/svn/asterisk/team/group/media_formats/include/asterisk/smoother.h?view=auto&rev=406018
==============================================================================
--- team/group/media_formats/include/asterisk/smoother.h (added)
+++ team/group/media_formats/include/asterisk/smoother.h Tue Jan 21 10:34:38 2014
@@ -1,0 +1,92 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2005, Digium, Inc.
+ *
+ * Mark Spencer <markster at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ * \brief Asterisk internal frame definitions.
+ * \arg For an explanation of frames, see \ref Def_Frame
+ * \arg Frames are send of Asterisk channels, see \ref Def_Channel
+ */
+
+#ifndef _ASTERISK_SMOOTHER_H
+#define _ASTERISK_SMOOTHER_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <sys/time.h>
+
+#include "asterisk/format_pref.h"
+#include "asterisk/format.h"
+#include "asterisk/endian.h"
+#include "asterisk/linkedlists.h"
+
+#define AST_SMOOTHER_FLAG_G729		(1 << 0)
+#define AST_SMOOTHER_FLAG_BE		(1 << 1)
+
+/*! \name AST_Smoother
+*/
+/*@{ */
+/*! \page ast_smooth The AST Frame Smoother
+The ast_smoother interface was designed specifically
+to take frames of variant sizes and produce frames of a single expected
+size, precisely what you want to do.
+
+The basic interface is:
+
+- Initialize with ast_smoother_new()
+- Queue input frames with ast_smoother_feed()
+- Get output frames with ast_smoother_read()
+- when you're done, free the structure with ast_smoother_free()
+- Also see ast_smoother_test_flag(), ast_smoother_set_flags(), ast_smoother_get_flags(), ast_smoother_reset()
+*/
+struct ast_smoother;
+
+struct ast_smoother *ast_smoother_new(int bytes);
+void ast_smoother_set_flags(struct ast_smoother *smoother, int flags);
+int ast_smoother_get_flags(struct ast_smoother *smoother);
+int ast_smoother_test_flag(struct ast_smoother *s, int flag);
+void ast_smoother_free(struct ast_smoother *s);
+void ast_smoother_reset(struct ast_smoother *s, int bytes);
+
+/*!
+ * \brief Reconfigure an existing smoother to output a different number of bytes per frame
+ * \param s the smoother to reconfigure
+ * \param bytes the desired number of bytes per output frame
+ * \return nothing
+ *
+ */
+void ast_smoother_reconfigure(struct ast_smoother *s, int bytes);
+
+int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap);
+struct ast_frame *ast_smoother_read(struct ast_smoother *s);
+#define ast_smoother_feed(s,f) __ast_smoother_feed(s, f, 0)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 1)
+#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 0)
+#else
+#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 0)
+#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 1)
+#endif
+/*@} Doxygen marker */
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* _ASTERISK_SMOOTHER_H */

Propchange: team/group/media_formats/include/asterisk/smoother.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/group/media_formats/include/asterisk/smoother.h
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/group/media_formats/include/asterisk/smoother.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/group/media_formats/main/format.c
URL: http://svnview.digium.com/svn/asterisk/team/group/media_formats/main/format.c?view=diff&rev=406018&r1=406017&r2=406018
==============================================================================
--- team/group/media_formats/main/format.c (original)
+++ team/group/media_formats/main/format.c Tue Jan 21 10:34:38 2014
@@ -42,8 +42,18 @@
 #include "asterisk/cli.h"
 #include "asterisk/rtp_engine.h"
 #include "asterisk/config.h"
+#include "asterisk/smoother.h"
 
 #define FORMAT_CONFIG "codecs.conf"
+
+enum frame_type {
+	TYPE_HIGH,     /* 0x0 */
+	TYPE_LOW,      /* 0x1 */
+	TYPE_SILENCE,  /* 0x2 */
+	TYPE_DONTSEND  /* 0x3 */
+};
+
+#define TYPE_MASK 0x3
 
 /*!
  * \brief Container for all the format attribute interfaces.
@@ -1452,3 +1462,360 @@
 	f_list = ast_format_list_destroy(f_list);
 	return 0;
 }
+
+int ast_parse_allow_disallow(struct ast_codec_pref *pref, struct ast_format_cap *cap, const char *list, int allowing)
+{
+	int errors = 0, framems = 0, all = 0, iter_allowing;
+	char *parse = NULL, *this = NULL, *psize = NULL;
+	struct ast_format format;
+
+	parse = ast_strdupa(list);
+	while ((this = strsep(&parse, ","))) {
+		iter_allowing = allowing;
+		framems = 0;
+		if (*this == '!') {
+			this++;
+			iter_allowing = !allowing;
+		}
+		if ((psize = strrchr(this, ':'))) {
+			*psize++ = '\0';
+			ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
+			framems = atoi(psize);
+			if (framems < 0) {
+				framems = 0;
+				errors++;
+				ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
+			}
+		}
+		all = strcasecmp(this, "all") ? 0 : 1;
+
+		if (!all && !ast_getformatbyname(this, &format)) {
+			ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", iter_allowing ? "allow" : "disallow", this);
+			errors++;
+			continue;
+		}
+
+		if (cap) {
+			if (iter_allowing) {
+				if (all) {
+					ast_format_cap_add_all(cap);
+				} else {
+					ast_format_cap_add(cap, &format);
+				}
+			} else {
+				if (all) {
+					ast_format_cap_remove_all(cap);
+				} else {
+					ast_format_cap_remove(cap, &format);
+				}
+			}
+		}
+
+		if (pref) {
+			if (!all) {
+				if (iter_allowing) {
+					ast_codec_pref_append(pref, &format);
+					ast_codec_pref_setsize(pref, &format, framems);
+				} else {
+					ast_codec_pref_remove(pref, &format);
+				}
+			} else if (!iter_allowing) {
+				memset(pref, 0, sizeof(*pref));
+			} else {
+				ast_codec_pref_append_all(pref);
+			}
+		}
+	}
+	return errors;
+}
+
+
+static int g723_len(unsigned char buf)
+{
+	enum frame_type type = buf & TYPE_MASK;
+
+	switch(type) {
+	case TYPE_DONTSEND:
+		return 0;
+		break;
+	case TYPE_SILENCE:
+		return 4;
+		break;
+	case TYPE_HIGH:
+		return 24;
+		break;
+	case TYPE_LOW:
+		return 20;
+		break;
+	default:
+		ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
+	}
+	return -1;
+}
+
+static int g723_samples(unsigned char *buf, int maxlen)
+{
+	int pos = 0;
+	int samples = 0;
+	int res;
+	while(pos < maxlen) {
+		res = g723_len(buf[pos]);
+		if (res <= 0)
+			break;
+		samples += 240;
+		pos += res;
+	}
+	return samples;
+}
+
+static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
+{
+	int byte = bit / 8;       /* byte containing first bit */
+	int rem = 8 - (bit % 8);  /* remaining bits in first byte */
+	unsigned char ret = 0;
+
+	if (n <= 0 || n > 8)
+		return 0;
+
+	if (rem < n) {
+		ret = (data[byte] << (n - rem));
+		ret |= (data[byte + 1] >> (8 - n + rem));
+	} else {
+		ret = (data[byte] >> (rem - n));
+	}
+
+	return (ret & (0xff >> (8 - n)));
+}
+
+static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
+{
+	static const int SpeexWBSubModeSz[] = {
+		4, 36, 112, 192,
+		352, 0, 0, 0 };
+	int off = bit;
+	unsigned char c;
+
+	/* skip up to two wideband frames */
+	if (((len * 8 - off) >= 5) &&
+		get_n_bits_at(data, 1, off)) {
+		c = get_n_bits_at(data, 3, off + 1);
+		off += SpeexWBSubModeSz[c];
+
+		if (((len * 8 - off) >= 5) &&
+			get_n_bits_at(data, 1, off)) {
+			c = get_n_bits_at(data, 3, off + 1);
+			off += SpeexWBSubModeSz[c];
+
+			if (((len * 8 - off) >= 5) &&
+				get_n_bits_at(data, 1, off)) {
+				ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
+				return -1;
+			}
+		}
+
+	}
+	return off - bit;
+}
+
+static int speex_samples(unsigned char *data, int len)
+{
+	static const int SpeexSubModeSz[] = {
+		5, 43, 119, 160,
+		220, 300, 364, 492,
+		79, 0, 0, 0,
+		0, 0, 0, 0 };
+	static const int SpeexInBandSz[] = {
+		1, 1, 4, 4,
+		4, 4, 4, 4,
+		8, 8, 16, 16,
+		32, 32, 64, 64 };
+	int bit = 0;
+	int cnt = 0;
+	int off;
+	unsigned char c;
+
+	while ((len * 8 - bit) >= 5) {
+		/* skip wideband frames */
+		off = speex_get_wb_sz_at(data, len, bit);
+		if (off < 0)  {
+			ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
+			break;
+		}
+		bit += off;
+
+		if ((len * 8 - bit) < 5)
+			break;
+
+		/* get control bits */
+		c = get_n_bits_at(data, 5, bit);
+		bit += 5;
+
+		if (c == 15) {
+			/* terminator */
+			break;
+		} else if (c == 14) {
+			/* in-band signal; next 4 bits contain signal id */
+			c = get_n_bits_at(data, 4, bit);
+			bit += 4;
+			bit += SpeexInBandSz[c];
+		} else if (c == 13) {
+			/* user in-band; next 4 bits contain msg len */
+			c = get_n_bits_at(data, 4, bit);
+			bit += 4;
+			/* after which it's 5-bit signal id + c bytes of data */
+			bit += 5 + c * 8;
+		} else if (c > 8) {
+			/* unknown */
+			ast_log(LOG_WARNING, "Unknown speex control frame %d\n", c);
+			break;
+		} else {
+			/* skip number bits for submode (less the 5 control bits) */
+			bit += SpeexSubModeSz[c] - 5;
+			cnt += 160; /* new frame */
+		}
+	}
+	return cnt;
+}
+
+int ast_codec_get_samples(struct ast_frame *f)
+{
+	int samples = 0;
+
+	switch (f->subclass.format.id) {
+	case AST_FORMAT_SPEEX:
+		samples = speex_samples(f->data.ptr, f->datalen);
+		break;
+	case AST_FORMAT_SPEEX16:
+		samples = 2 * speex_samples(f->data.ptr, f->datalen);
+		break;
+	case AST_FORMAT_SPEEX32:
+		samples = 4 * speex_samples(f->data.ptr, f->datalen);
+		break;
+	case AST_FORMAT_G723_1:
+		samples = g723_samples(f->data.ptr, f->datalen);
+		break;
+	case AST_FORMAT_ILBC:
+		samples = 240 * (f->datalen / 50);
+		break;
+	case AST_FORMAT_GSM:
+		samples = 160 * (f->datalen / 33);
+		break;
+	case AST_FORMAT_G729A:
+		samples = f->datalen * 8;
+		break;
+	case AST_FORMAT_SLINEAR:
+	case AST_FORMAT_SLINEAR16:
+		samples = f->datalen / 2;
+		break;
+	case AST_FORMAT_LPC10:
+		/* assumes that the RTP packet contains one LPC10 frame */
+		samples = 22 * 8;
+		samples += (((char *)(f->data.ptr))[7] & 0x1) * 8;
+		break;
+	case AST_FORMAT_ULAW:
+	case AST_FORMAT_ALAW:
+	case AST_FORMAT_TESTLAW:
+		samples = f->datalen;
+		break;
+	case AST_FORMAT_G722:
+	case AST_FORMAT_ADPCM:
+	case AST_FORMAT_G726:
+	case AST_FORMAT_G726_AAL2:
+		samples = f->datalen * 2;
+		break;
+	case AST_FORMAT_SIREN7:
+		/* 16,000 samples per second at 32kbps is 4,000 bytes per second */
+		samples = f->datalen * (16000 / 4000);
+		break;
+	case AST_FORMAT_SIREN14:
+		/* 32,000 samples per second at 48kbps is 6,000 bytes per second */
+		samples = (int) f->datalen * ((float) 32000 / 6000);
+		break;
+	case AST_FORMAT_G719:
+		/* 48,000 samples per second at 64kbps is 8,000 bytes per second */
+		samples = (int) f->datalen * ((float) 48000 / 8000);
+		break;
+	case AST_FORMAT_SILK:
+		if (!(ast_format_isset(&f->subclass.format,
+			SILK_ATTR_KEY_SAMP_RATE,
+			SILK_ATTR_VAL_SAMP_24KHZ,
+			AST_FORMAT_ATTR_END))) {
+			return 480;
+		} else if (!(ast_format_isset(&f->subclass.format,
+			SILK_ATTR_KEY_SAMP_RATE,
+			SILK_ATTR_VAL_SAMP_16KHZ,
+			AST_FORMAT_ATTR_END))) {
+			return 320;
+		} else if (!(ast_format_isset(&f->subclass.format,
+			SILK_ATTR_KEY_SAMP_RATE,
+			SILK_ATTR_VAL_SAMP_12KHZ,
+			AST_FORMAT_ATTR_END))) {
+			return 240;
+		} else {
+			return 160;
+		}
+	case AST_FORMAT_CELT:
+		/* TODO This assumes 20ms delivery right now, which is incorrect */
+		samples = ast_format_rate(&f->subclass.format) / 50;
+		break;
+	case AST_FORMAT_OPUS:
+		/* TODO This assumes 20ms delivery right now, which is incorrect */
+		samples = 960;
+		break;
+	default:
+		ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(&f->subclass.format));
+	}
+	return samples;
+}
+
+int ast_codec_get_len(struct ast_format *format, int samples)
+{
+	int len = 0;
+
+	/* XXX Still need speex, and lpc10 XXX */
+	switch(format->id) {
+	case AST_FORMAT_G723_1:
+		len = (samples / 240) * 20;
+		break;
+	case AST_FORMAT_ILBC:
+		len = (samples / 240) * 50;
+		break;
+	case AST_FORMAT_GSM:
+		len = (samples / 160) * 33;
+		break;
+	case AST_FORMAT_G729A:
+		len = samples / 8;
+		break;
+	case AST_FORMAT_SLINEAR:
+	case AST_FORMAT_SLINEAR16:
+		len = samples * 2;
+		break;
+	case AST_FORMAT_ULAW:
+	case AST_FORMAT_ALAW:
+	case AST_FORMAT_TESTLAW:
+		len = samples;
+		break;
+	case AST_FORMAT_G722:
+	case AST_FORMAT_ADPCM:
+	case AST_FORMAT_G726:
+	case AST_FORMAT_G726_AAL2:
+		len = samples / 2;
+		break;
+	case AST_FORMAT_SIREN7:
+		/* 16,000 samples per second at 32kbps is 4,000 bytes per second */
+		len = samples / (16000 / 4000);
+		break;
+	case AST_FORMAT_SIREN14:
+		/* 32,000 samples per second at 48kbps is 6,000 bytes per second */
+		len = (int) samples / ((float) 32000 / 6000);
+		break;
+	case AST_FORMAT_G719:
+		/* 48,000 samples per second at 64kbps is 8,000 bytes per second */
+		len = (int) samples / ((float) 48000 / 8000);
+		break;
+	default:
+		ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
+	}
+
+	return len;
+}

Modified: team/group/media_formats/main/frame.c
URL: http://svnview.digium.com/svn/asterisk/team/group/media_formats/main/frame.c?view=diff&rev=406018&r1=406017&r2=406018
==============================================================================
--- team/group/media_formats/main/frame.c (original)
+++ team/group/media_formats/main/frame.c Tue Jan 21 10:34:38 2014
@@ -71,198 +71,7 @@
 };
 #endif
 
-#define SMOOTHER_SIZE 8000
-
-enum frame_type {
-	TYPE_HIGH,     /* 0x0 */
-	TYPE_LOW,      /* 0x1 */
-	TYPE_SILENCE,  /* 0x2 */
-	TYPE_DONTSEND  /* 0x3 */
-};
-
-#define TYPE_MASK 0x3
-
-struct ast_smoother {
-	int size;
-	struct ast_format format;
-	int flags;
-	float samplesperbyte;
-	unsigned int opt_needs_swap:1;
-	struct ast_frame f;
-	struct timeval delivery;
-	char data[SMOOTHER_SIZE];
-	char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
-	struct ast_frame *opt;
-	int len;
-};
-
 struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
-
-static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
-{
-	if (s->flags & AST_SMOOTHER_FLAG_G729) {
-		if (s->len % 10) {
-			ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
-			return 0;
-		}
-	}
-	if (swap) {
-		ast_swapcopy_samples(s->data + s->len, f->data.ptr, f->samples);
-	} else {
-		memcpy(s->data + s->len, f->data.ptr, f->datalen);
-	}
-	/* If either side is empty, reset the delivery time */
-	if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) {	/* XXX really ? */
-		s->delivery = f->delivery;
-	}
-	s->len += f->datalen;
-
-	return 0;
-}
-
-void ast_smoother_reset(struct ast_smoother *s, int bytes)
-{
-	memset(s, 0, sizeof(*s));
-	s->size = bytes;
-}
-
-void ast_smoother_reconfigure(struct ast_smoother *s, int bytes)
-{
-	/* if there is no change, then nothing to do */
-	if (s->size == bytes) {
-		return;
-	}
-	/* set the new desired output size */
-	s->size = bytes;
-	/* if there is no 'optimized' frame in the smoother,
-	 *   then there is nothing left to do
-	 */
-	if (!s->opt) {
-		return;
-	}
-	/* there is an 'optimized' frame here at the old size,
-	 * but it must now be put into the buffer so the data
-	 * can be extracted at the new size
-	 */
-	smoother_frame_feed(s, s->opt, s->opt_needs_swap);
-	s->opt = NULL;
-}
-
-struct ast_smoother *ast_smoother_new(int size)
-{
-	struct ast_smoother *s;
-	if (size < 1)
-		return NULL;
-	if ((s = ast_malloc(sizeof(*s))))
-		ast_smoother_reset(s, size);
-	return s;
-}
-
-int ast_smoother_get_flags(struct ast_smoother *s)
-{
-	return s->flags;
-}
-
-void ast_smoother_set_flags(struct ast_smoother *s, int flags)
-{
-	s->flags = flags;
-}
-
-int ast_smoother_test_flag(struct ast_smoother *s, int flag)
-{
-	return (s->flags & flag);
-}
-
-int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
-{
-	if (f->frametype != AST_FRAME_VOICE) {
-		ast_log(LOG_WARNING, "Huh?  Can't smooth a non-voice frame!\n");
-		return -1;
-	}
-	if (!s->format.id) {
-		ast_format_copy(&s->format, &f->subclass.format);
-		s->samplesperbyte = (float)f->samples / (float)f->datalen;
-	} else if (ast_format_cmp(&s->format, &f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
-		ast_log(LOG_WARNING, "Smoother was working on %s format frames, now trying to feed %s?\n",
-			ast_getformatname(&s->format), ast_getformatname(&f->subclass.format));
-		return -1;
-	}
-	if (s->len + f->datalen > SMOOTHER_SIZE) {
-		ast_log(LOG_WARNING, "Out of smoother space\n");
-		return -1;
-	}
-	if (((f->datalen == s->size) ||
-	     ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729))) &&
-	    !s->opt &&
-	    !s->len &&
-	    (f->offset >= AST_MIN_OFFSET)) {
-		/* Optimize by sending the frame we just got
-		   on the next read, thus eliminating the douple
-		   copy */
-		if (swap)
-			ast_swapcopy_samples(f->data.ptr, f->data.ptr, f->samples);
-		s->opt = f;
-		s->opt_needs_swap = swap ? 1 : 0;
-		return 0;
-	}
-
-	return smoother_frame_feed(s, f, swap);
-}
-
-struct ast_frame *ast_smoother_read(struct ast_smoother *s)
-{
-	struct ast_frame *opt;
-	int len;
-
-	/* IF we have an optimization frame, send it */
-	if (s->opt) {
-		if (s->opt->offset < AST_FRIENDLY_OFFSET)
-			ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
-							s->opt->offset);
-		opt = s->opt;
-		s->opt = NULL;
-		return opt;
-	}
-
-	/* Make sure we have enough data */
-	if (s->len < s->size) {
-		/* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
-		if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->len % 10)))
-			return NULL;
-	}
-	len = s->size;
-	if (len > s->len)
-		len = s->len;
-	/* Make frame */
-	s->f.frametype = AST_FRAME_VOICE;
-	ast_format_copy(&s->f.subclass.format, &s->format);
-	s->f.data.ptr = s->framedata + AST_FRIENDLY_OFFSET;
-	s->f.offset = AST_FRIENDLY_OFFSET;
-	s->f.datalen = len;
-	/* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
-	s->f.samples = len * s->samplesperbyte;	/* XXX rounding */
-	s->f.delivery = s->delivery;
-	/* Fill Data */
-	memcpy(s->f.data.ptr, s->data, len);
-	s->len -= len;
-	/* Move remaining data to the front if applicable */
-	if (s->len) {
-		/* In principle this should all be fine because if we are sending
-		   G.729 VAD, the next timestamp will take over anyawy */
-		memmove(s->data, s->data + len, s->len);
-		if (!ast_tvzero(s->delivery)) {
-			/* If we have delivery time, increment it, otherwise, leave it at 0 */
-			s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, ast_format_rate(&s->format)));
-		}
-	}
-	/* Return frame */
-	return &s->f;
-}
-
-void ast_smoother_free(struct ast_smoother *s)
-{
-	ast_free(s);
-}
 
 static struct ast_frame *ast_frame_header_new(void)
 {
@@ -808,362 +617,6 @@
 			    term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
 }
 
-int ast_parse_allow_disallow(struct ast_codec_pref *pref, struct ast_format_cap *cap, const char *list, int allowing)
-{
-	int errors = 0, framems = 0, all = 0, iter_allowing;
-	char *parse = NULL, *this = NULL, *psize = NULL;
-	struct ast_format format;
-
-	parse = ast_strdupa(list);
-	while ((this = strsep(&parse, ","))) {
-		iter_allowing = allowing;
-		framems = 0;
-		if (*this == '!') {
-			this++;
-			iter_allowing = !allowing;
-		}
-		if ((psize = strrchr(this, ':'))) {
-			*psize++ = '\0';
-			ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
-			framems = atoi(psize);
-			if (framems < 0) {
-				framems = 0;
-				errors++;
-				ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
-			}
-		}
-		all = strcasecmp(this, "all") ? 0 : 1;
-
-		if (!all && !ast_getformatbyname(this, &format)) {
-			ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", iter_allowing ? "allow" : "disallow", this);
-			errors++;
-			continue;
-		}
-
-		if (cap) {
-			if (iter_allowing) {
-				if (all) {
-					ast_format_cap_add_all(cap);
-				} else {
-					ast_format_cap_add(cap, &format);
-				}
-			} else {
-				if (all) {
-					ast_format_cap_remove_all(cap);
-				} else {
-					ast_format_cap_remove(cap, &format);
-				}
-			}
-		}
-
-		if (pref) {
-			if (!all) {
-				if (iter_allowing) {
-					ast_codec_pref_append(pref, &format);
-					ast_codec_pref_setsize(pref, &format, framems);
-				} else {
-					ast_codec_pref_remove(pref, &format);
-				}
-			} else if (!iter_allowing) {
-				memset(pref, 0, sizeof(*pref));
-			} else {
-				ast_codec_pref_append_all(pref);
-			}
-		}
-	}
-	return errors;
-}
-
-static int g723_len(unsigned char buf)
-{
-	enum frame_type type = buf & TYPE_MASK;
-
-	switch(type) {
-	case TYPE_DONTSEND:
-		return 0;
-		break;
-	case TYPE_SILENCE:
-		return 4;
-		break;
-	case TYPE_HIGH:
-		return 24;
-		break;
-	case TYPE_LOW:
-		return 20;
-		break;
-	default:
-		ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
-	}
-	return -1;
-}
-
-static int g723_samples(unsigned char *buf, int maxlen)
-{
-	int pos = 0;
-	int samples = 0;
-	int res;
-	while(pos < maxlen) {
-		res = g723_len(buf[pos]);
-		if (res <= 0)
-			break;
-		samples += 240;
-		pos += res;
-	}
-	return samples;
-}
-
-static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
-{
-	int byte = bit / 8;       /* byte containing first bit */
-	int rem = 8 - (bit % 8);  /* remaining bits in first byte */
-	unsigned char ret = 0;
-
-	if (n <= 0 || n > 8)
-		return 0;
-
-	if (rem < n) {
-		ret = (data[byte] << (n - rem));
-		ret |= (data[byte + 1] >> (8 - n + rem));
-	} else {
-		ret = (data[byte] >> (rem - n));
-	}
-
-	return (ret & (0xff >> (8 - n)));
-}
-
-static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
-{
-	static const int SpeexWBSubModeSz[] = {
-		4, 36, 112, 192,
-		352, 0, 0, 0 };
-	int off = bit;
-	unsigned char c;
-
-	/* skip up to two wideband frames */
-	if (((len * 8 - off) >= 5) &&
-		get_n_bits_at(data, 1, off)) {
-		c = get_n_bits_at(data, 3, off + 1);
-		off += SpeexWBSubModeSz[c];
-
-		if (((len * 8 - off) >= 5) &&
-			get_n_bits_at(data, 1, off)) {
-			c = get_n_bits_at(data, 3, off + 1);
-			off += SpeexWBSubModeSz[c];
-
-			if (((len * 8 - off) >= 5) &&
-				get_n_bits_at(data, 1, off)) {
-				ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
-				return -1;
-			}
-		}
-
-	}
-	return off - bit;
-}
-
-static int speex_samples(unsigned char *data, int len)
-{
-	static const int SpeexSubModeSz[] = {
-		5, 43, 119, 160,
-		220, 300, 364, 492,
-		79, 0, 0, 0,
-		0, 0, 0, 0 };
-	static const int SpeexInBandSz[] = {
-		1, 1, 4, 4,
-		4, 4, 4, 4,
-		8, 8, 16, 16,
-		32, 32, 64, 64 };
-	int bit = 0;
-	int cnt = 0;
-	int off;
-	unsigned char c;
-
-	while ((len * 8 - bit) >= 5) {
-		/* skip wideband frames */
-		off = speex_get_wb_sz_at(data, len, bit);
-		if (off < 0)  {
-			ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
-			break;
-		}
-		bit += off;
-
-		if ((len * 8 - bit) < 5)
-			break;
-
-		/* get control bits */
-		c = get_n_bits_at(data, 5, bit);
-		bit += 5;
-
-		if (c == 15) {
-			/* terminator */
-			break;
-		} else if (c == 14) {
-			/* in-band signal; next 4 bits contain signal id */
-			c = get_n_bits_at(data, 4, bit);
-			bit += 4;
-			bit += SpeexInBandSz[c];
-		} else if (c == 13) {
-			/* user in-band; next 4 bits contain msg len */
-			c = get_n_bits_at(data, 4, bit);
-			bit += 4;
-			/* after which it's 5-bit signal id + c bytes of data */
-			bit += 5 + c * 8;
-		} else if (c > 8) {
-			/* unknown */
-			ast_log(LOG_WARNING, "Unknown speex control frame %d\n", c);
-			break;
-		} else {
-			/* skip number bits for submode (less the 5 control bits) */
-			bit += SpeexSubModeSz[c] - 5;
-			cnt += 160; /* new frame */
-		}
-	}
-	return cnt;
-}
-
-int ast_codec_get_samples(struct ast_frame *f)
-{
-	int samples = 0;
-
-	switch (f->subclass.format.id) {
-	case AST_FORMAT_SPEEX:
-		samples = speex_samples(f->data.ptr, f->datalen);
-		break;
-	case AST_FORMAT_SPEEX16:
-		samples = 2 * speex_samples(f->data.ptr, f->datalen);
-		break;
-	case AST_FORMAT_SPEEX32:
-		samples = 4 * speex_samples(f->data.ptr, f->datalen);
-		break;
-	case AST_FORMAT_G723_1:
-		samples = g723_samples(f->data.ptr, f->datalen);
-		break;
-	case AST_FORMAT_ILBC:
-		samples = 240 * (f->datalen / 50);
-		break;
-	case AST_FORMAT_GSM:
-		samples = 160 * (f->datalen / 33);
-		break;
-	case AST_FORMAT_G729A:
-		samples = f->datalen * 8;
-		break;
-	case AST_FORMAT_SLINEAR:
-	case AST_FORMAT_SLINEAR16:
-		samples = f->datalen / 2;
-		break;
-	case AST_FORMAT_LPC10:
-		/* assumes that the RTP packet contains one LPC10 frame */
-		samples = 22 * 8;
-		samples += (((char *)(f->data.ptr))[7] & 0x1) * 8;
-		break;
-	case AST_FORMAT_ULAW:
-	case AST_FORMAT_ALAW:
-	case AST_FORMAT_TESTLAW:
-		samples = f->datalen;
-		break;
-	case AST_FORMAT_G722:
-	case AST_FORMAT_ADPCM:
-	case AST_FORMAT_G726:
-	case AST_FORMAT_G726_AAL2:
-		samples = f->datalen * 2;
-		break;
-	case AST_FORMAT_SIREN7:
-		/* 16,000 samples per second at 32kbps is 4,000 bytes per second */
-		samples = f->datalen * (16000 / 4000);
-		break;
-	case AST_FORMAT_SIREN14:
-		/* 32,000 samples per second at 48kbps is 6,000 bytes per second */
-		samples = (int) f->datalen * ((float) 32000 / 6000);
-		break;
-	case AST_FORMAT_G719:
-		/* 48,000 samples per second at 64kbps is 8,000 bytes per second */
-		samples = (int) f->datalen * ((float) 48000 / 8000);
-		break;
-	case AST_FORMAT_SILK:
-		if (!(ast_format_isset(&f->subclass.format,
-			SILK_ATTR_KEY_SAMP_RATE,
-			SILK_ATTR_VAL_SAMP_24KHZ,
-			AST_FORMAT_ATTR_END))) {
-			return 480;
-		} else if (!(ast_format_isset(&f->subclass.format,
-			SILK_ATTR_KEY_SAMP_RATE,
-			SILK_ATTR_VAL_SAMP_16KHZ,
-			AST_FORMAT_ATTR_END))) {
-			return 320;
-		} else if (!(ast_format_isset(&f->subclass.format,
-			SILK_ATTR_KEY_SAMP_RATE,
-			SILK_ATTR_VAL_SAMP_12KHZ,
-			AST_FORMAT_ATTR_END))) {
-			return 240;
-		} else {
-			return 160;
-		}
-	case AST_FORMAT_CELT:
-		/* TODO This assumes 20ms delivery right now, which is incorrect */
-		samples = ast_format_rate(&f->subclass.format) / 50;
-		break;
-	case AST_FORMAT_OPUS:
-		/* TODO This assumes 20ms delivery right now, which is incorrect */
-		samples = 960;
-		break;
-	default:
-		ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(&f->subclass.format));
-	}
-	return samples;
-}
-
-int ast_codec_get_len(struct ast_format *format, int samples)
-{
-	int len = 0;
-
-	/* XXX Still need speex, and lpc10 XXX */
-	switch(format->id) {
-	case AST_FORMAT_G723_1:
-		len = (samples / 240) * 20;
-		break;
-	case AST_FORMAT_ILBC:
-		len = (samples / 240) * 50;
-		break;
-	case AST_FORMAT_GSM:
-		len = (samples / 160) * 33;
-		break;
-	case AST_FORMAT_G729A:
-		len = samples / 8;
-		break;
-	case AST_FORMAT_SLINEAR:
-	case AST_FORMAT_SLINEAR16:
-		len = samples * 2;
-		break;
-	case AST_FORMAT_ULAW:
-	case AST_FORMAT_ALAW:
-	case AST_FORMAT_TESTLAW:
-		len = samples;
-		break;
-	case AST_FORMAT_G722:
-	case AST_FORMAT_ADPCM:
-	case AST_FORMAT_G726:
-	case AST_FORMAT_G726_AAL2:
-		len = samples / 2;
-		break;
-	case AST_FORMAT_SIREN7:
-		/* 16,000 samples per second at 32kbps is 4,000 bytes per second */
-		len = samples / (16000 / 4000);
-		break;
-	case AST_FORMAT_SIREN14:
-		/* 32,000 samples per second at 48kbps is 6,000 bytes per second */
-		len = (int) samples / ((float) 32000 / 6000);
-		break;
-	case AST_FORMAT_G719:
-		/* 48,000 samples per second at 64kbps is 8,000 bytes per second */
-		len = (int) samples / ((float) 48000 / 8000);
-		break;
-	default:
-		ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
-	}
-
-	return len;
-}
-
 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
 {
 	int count;

Added: team/group/media_formats/main/smoother.c
URL: http://svnview.digium.com/svn/asterisk/team/group/media_formats/main/smoother.c?view=auto&rev=406018
==============================================================================
--- team/group/media_formats/main/smoother.c (added)
+++ team/group/media_formats/main/smoother.c Tue Jan 21 10:34:38 2014
@@ -1,0 +1,229 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2005, Digium, Inc.
+ *
+ * Mark Spencer <markster at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Frame smoother manipulation routines
+ *
+ * \author Mark Spencer <markster at digium.com>
+ */
+
+/*** MODULEINFO
+	<support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/_private.h"
+#include "asterisk/lock.h"
+#include "asterisk/frame.h"
+#include "asterisk/channel.h"
+#include "asterisk/cli.h"
+#include "asterisk/term.h"
+#include "asterisk/utils.h"
+#include "asterisk/threadstorage.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/translate.h"
+#include "asterisk/dsp.h"
+#include "asterisk/file.h"
+#include "asterisk/smoother.h"
+
+#define SMOOTHER_SIZE 8000
+
+struct ast_smoother {
+	int size;
+	struct ast_format format;
+	int flags;
+	float samplesperbyte;
+	unsigned int opt_needs_swap:1;
+	struct ast_frame f;
+	struct timeval delivery;
+	char data[SMOOTHER_SIZE];
+	char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
+	struct ast_frame *opt;
+	int len;
+};
+
+static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
+{
+	if (s->flags & AST_SMOOTHER_FLAG_G729) {
+		if (s->len % 10) {
+			ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
+			return 0;
+		}
+	}
+	if (swap) {
+		ast_swapcopy_samples(s->data + s->len, f->data.ptr, f->samples);
+	} else {
+		memcpy(s->data + s->len, f->data.ptr, f->datalen);
+	}
+	/* If either side is empty, reset the delivery time */
+	if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) {	/* XXX really ? */
+		s->delivery = f->delivery;
+	}
+	s->len += f->datalen;
+
+	return 0;
+}
+
+void ast_smoother_reset(struct ast_smoother *s, int bytes)
+{
+	memset(s, 0, sizeof(*s));
+	s->size = bytes;
+}
+
+void ast_smoother_reconfigure(struct ast_smoother *s, int bytes)
+{
+	/* if there is no change, then nothing to do */
+	if (s->size == bytes) {
+		return;
+	}
+	/* set the new desired output size */
+	s->size = bytes;
+	/* if there is no 'optimized' frame in the smoother,
+	 *   then there is nothing left to do
+	 */
+	if (!s->opt) {
+		return;
+	}
+	/* there is an 'optimized' frame here at the old size,
+	 * but it must now be put into the buffer so the data
+	 * can be extracted at the new size
+	 */
+	smoother_frame_feed(s, s->opt, s->opt_needs_swap);
+	s->opt = NULL;
+}
+
+struct ast_smoother *ast_smoother_new(int size)
+{
+	struct ast_smoother *s;
+	if (size < 1)
+		return NULL;
+	if ((s = ast_malloc(sizeof(*s))))
+		ast_smoother_reset(s, size);
+	return s;
+}
+
+int ast_smoother_get_flags(struct ast_smoother *s)
+{
+	return s->flags;
+}
+
+void ast_smoother_set_flags(struct ast_smoother *s, int flags)
+{
+	s->flags = flags;
+}
+
+int ast_smoother_test_flag(struct ast_smoother *s, int flag)
+{
+	return (s->flags & flag);
+}
+
+int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
+{
+	if (f->frametype != AST_FRAME_VOICE) {
+		ast_log(LOG_WARNING, "Huh?  Can't smooth a non-voice frame!\n");
+		return -1;
+	}
+	if (!s->format.id) {
+		ast_format_copy(&s->format, &f->subclass.format);
+		s->samplesperbyte = (float)f->samples / (float)f->datalen;
+	} else if (ast_format_cmp(&s->format, &f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+		ast_log(LOG_WARNING, "Smoother was working on %s format frames, now trying to feed %s?\n",
+			ast_getformatname(&s->format), ast_getformatname(&f->subclass.format));
+		return -1;
+	}
+	if (s->len + f->datalen > SMOOTHER_SIZE) {
+		ast_log(LOG_WARNING, "Out of smoother space\n");
+		return -1;
+	}
+	if (((f->datalen == s->size) ||
+	     ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729))) &&
+	    !s->opt &&
+	    !s->len &&
+	    (f->offset >= AST_MIN_OFFSET)) {
+		/* Optimize by sending the frame we just got
+		   on the next read, thus eliminating the douple
+		   copy */
+		if (swap)
+			ast_swapcopy_samples(f->data.ptr, f->data.ptr, f->samples);
+		s->opt = f;
+		s->opt_needs_swap = swap ? 1 : 0;
+		return 0;
+	}
+
+	return smoother_frame_feed(s, f, swap);
+}
+
+struct ast_frame *ast_smoother_read(struct ast_smoother *s)
+{
+	struct ast_frame *opt;
+	int len;
+

[... 91 lines stripped ...]



More information about the asterisk-commits mailing list