aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroej <oej@f38db490-d61c-443f-a65b-d21fe96a405b>2006-03-30 06:07:04 +0000
committeroej <oej@f38db490-d61c-443f-a65b-d21fe96a405b>2006-03-30 06:07:04 +0000
commit60636c259914d27a04b43c8bc26dece1871d876a (patch)
tree57c1cb7f263e43e28f5b083076ff222662216773
parenta9a990c34439999f57a0993ddf1b81c8501bae91 (diff)
Issue #5374 - Enable internal timing of generators (cmantunes)
Thanks everyone involved for hard work, testing and testing! git-svn-id: http://svn.digium.com/svn/asterisk/trunk@16473 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--Makefile2
-rw-r--r--apps/app_milliwatt.c21
-rw-r--r--apps/app_sms.c27
-rw-r--r--asterisk.88
-rw-r--r--asterisk.c12
-rw-r--r--asterisk.sgml15
-rw-r--r--channel.c28
-rw-r--r--channels/chan_sip.c3
-rw-r--r--doc/asterisk-conf.txt1
-rw-r--r--include/asterisk/channel.h10
-rw-r--r--include/asterisk/options.h6
11 files changed, 97 insertions, 36 deletions
diff --git a/Makefile b/Makefile
index 4414a7670..b4f722c96 100644
--- a/Makefile
+++ b/Makefile
@@ -788,6 +788,8 @@ samples: adsi
echo ";astctlowner = root" ; \
echo ";astctlgroup = apache" ; \
echo ";astctl = asterisk.ctl" ; \
+ echo ";[options]" ; \
+ echo ";internal_timing = yes" ; \
) > $(DESTDIR)$(ASTCONFPATH) ; \
else \
echo "Skipping asterisk.conf creation"; \
diff --git a/apps/app_milliwatt.c b/apps/app_milliwatt.c
index 69fc3887f..27eb9adb5 100644
--- a/apps/app_milliwatt.c
+++ b/apps/app_milliwatt.c
@@ -71,20 +71,27 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
{
struct ast_frame wf;
unsigned char buf[AST_FRIENDLY_OFFSET + 640];
- int i,*indexp = (int *) data;
-
- if (len + AST_FRIENDLY_OFFSET > sizeof(buf))
- {
- ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)(sizeof(buf) - AST_FRIENDLY_OFFSET),len);
- len = sizeof(buf) - AST_FRIENDLY_OFFSET;
+ const int maxsamples = sizeof (buf) / sizeof (buf[0]);
+ int i, *indexp = (int *) data;
+
+ /* Instead of len, use samples, because channel.c generator_force
+ * generate(chan, tmp, 0, 160) ignores len. In any case, len is
+ * a multiple of samples, given by number of samples times bytes per
+ * sample. In the case of ulaw, len = samples. for signed linear
+ * len = 2 * samples */
+
+ if (samples > maxsamples) {
+ ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples);
+ samples = maxsamples;
}
+ len = samples * sizeof (buf[0]);
wf.frametype = AST_FRAME_VOICE;
wf.subclass = AST_FORMAT_ULAW;
wf.offset = AST_FRIENDLY_OFFSET;
wf.mallocd = 0;
wf.data = buf + AST_FRIENDLY_OFFSET;
wf.datalen = len;
- wf.samples = wf.datalen;
+ wf.samples = samples;
wf.src = "app_milliwatt";
wf.delivery.tv_sec = 0;
wf.delivery.tv_usec = 0;
diff --git a/apps/app_sms.c b/apps/app_sms.c
index d9b85bfaa..a607d359e 100644
--- a/apps/app_sms.c
+++ b/apps/app_sms.c
@@ -1177,32 +1177,31 @@ static int sms_generate (struct ast_channel *chan, void *data, int len, int samp
{
struct ast_frame f = { 0 };
unsigned char waste[AST_FRIENDLY_OFFSET];
+#define MAXSAMPLES (800)
#ifdef OUTALAW
- unsigned char buf[800];
+ unsigned char buf[MAXSAMPLES];
#else
- signed short buf[800];
+ signed short buf[MAXSAMPLES];
#endif
+#define SAMPLE2LEN (sizeof (buf[0]))
sms_t *h = data;
int i;
- if (len > sizeof (buf)) {
- ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len);
- len = sizeof (buf);
-#ifdef OUTALAW
- samples = len;
-#else
- samples = len / 2;
-#endif
+ if (samples > MAXSAMPLES) {
+ ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n",
+ MAXSAMPLES, samples);
+ samples = MAXSAMPLES;
}
- waste[0] = 0; /* make compiler happy */
+ len = samples * SAMPLE2LEN;
+
+ waste[0] = 0; /* make compiler happy */
f.frametype = AST_FRAME_VOICE;
#ifdef OUTALAW
f.subclass = AST_FORMAT_ALAW;
- f.datalen = samples;
#else
f.subclass = AST_FORMAT_SLINEAR;
- f.datalen = samples * 2;
#endif
+ f.datalen = len;
f.offset = AST_FRIENDLY_OFFSET;
f.mallocd = 0;
f.data = buf;
@@ -1254,6 +1253,8 @@ static int sms_generate (struct ast_channel *chan, void *data, int len, int samp
return -1;
}
return 0;
+#undef SAMPLE2LEN
+#undef MAXSAMPLES
}
static void sms_process (sms_t * h, int samples, signed short *data)
diff --git a/asterisk.8 b/asterisk.8
index 28ea0ffde..b90e342ff 100644
--- a/asterisk.8
+++ b/asterisk.8
@@ -9,7 +9,7 @@
asterisk \- All-purpose telephony server.
.SH SYNOPSIS
-\fBasterisk\fR [ \fB-tThfdvVqpRgcin\fR ] [ \fB-C \fIfile\fB\fR ] [ \fB-U \fIuser\fB\fR ] [ \fB-G \fIgroup\fB\fR ] [ \fB-x \fIcommand\fB\fR ] [ \fB-M \fIvalue\fB\fR ]
+\fBasterisk\fR [ \fB-tThfdvVqpRgciIn\fR ] [ \fB-C \fIfile\fB\fR ] [ \fB-U \fIuser\fB\fR ] [ \fB-G \fIgroup\fB\fR ] [ \fB-x \fIcommand\fB\fR ] [ \fB-M \fIvalue\fB\fR ]
\fBasterisk -r\fR [ \fB-v\fR ] [ \fB-x \fIcommand\fB\fR ]
@@ -114,6 +114,12 @@ to a running Asterisk process and provide a console interface
for controlling it. Additionally, if connection to the Asterisk
process is lost, attempt to reconnect for as long as 30 seconds.
.TP
+\fB-I\fR
+Enable internal timing if Zaptel timer is available
+The default behaviour is that outbound packets are phase locked
+to inbound packets. Enabling this switch causes them to be
+locked to the internal Zaptel timer instead.
+.TP
\fB-t\fR
When recording files, write them first into a temporary holding directory,
then move them into the final location when done.
diff --git a/asterisk.c b/asterisk.c
index 9ef3c448a..9f3b2342e 100644
--- a/asterisk.c
+++ b/asterisk.c
@@ -161,6 +161,9 @@ int option_debug = 0; /*!< Debug level */
double option_maxload = 0.0; /*!< Max load avg on system */
int option_maxcalls = 0; /*!< Max number of active calls */
+int option_internal_timing = 0;
+
+
/*! @} */
char record_cache_dir[AST_CACHE_DIR_LEN] = AST_TMP_DIR;
@@ -1970,6 +1973,9 @@ static void ast_readconfig(void)
/* Transmit SLINEAR silence while a channel is being recorded */
} else if (!strcasecmp(v->name, "transmit_silence_during_record")) {
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
+ /* Enable internal timing */
+ } else if (!strcasecmp(v->name, "internal_timing")) {
+ option_internal_timing = ast_true(v->value);
} else if (!strcasecmp(v->name, "maxcalls")) {
if ((sscanf(v->value, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
option_maxcalls = 0;
@@ -2049,7 +2055,7 @@ int main(int argc, char *argv[])
}
*/
/* Check for options */
- while((c=getopt(argc, argv, "tThfdvVqprRgcinx:U:G:C:L:M:")) != -1) {
+ while((c=getopt(argc, argv, "tThfdvVqprRgciInx:U:G:C:L:M:")) != -1) {
switch(c) {
case 'd':
option_debug++;
@@ -2088,6 +2094,7 @@ int main(int argc, char *argv[])
case 'q':
ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET);
break;
+ break;
case 't':
ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES);
break;
@@ -2102,6 +2109,9 @@ int main(int argc, char *argv[])
ast_copy_string(ast_config_AST_CONFIG_FILE, optarg, sizeof(ast_config_AST_CONFIG_FILE));
ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
break;
+ case 'I':
+ option_internal_timing = 1;
+ break;
case 'i':
ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
break;
diff --git a/asterisk.sgml b/asterisk.sgml
index 663a816be..ff257ff67 100644
--- a/asterisk.sgml
+++ b/asterisk.sgml
@@ -21,7 +21,7 @@
<refsynopsisdiv>
<cmdsynopsis>
<command>asterisk</command>
-<arg><option>-tThfdvVqpRgcin</option></arg>
+<arg><option>-tThfdvVqpRgciIn</option></arg>
<arg><option>-C </option><replaceable class="parameter">file</replaceable></arg>
<arg><option>-U </option><replaceable class="parameter">user</replaceable></arg>
<arg><option>-G </option><replaceable class="parameter">group</replaceable></arg>
@@ -38,7 +38,7 @@
</refsynopsisdiv>
<refsect1>
<refsect1info>
- <date>2004-07-01</date>
+ <date>2006-03-29</date>
</refsect1info>
<title>DESCRIPTION</title>
<para>
@@ -154,6 +154,17 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term>-I</term>
+ <listitem>
+ <para>
+ Enable internal timing if Zaptel timing is available.
+ The default behaviour is that outbound packets are phase locked
+ to inbound packets. Enabling this switch causes them to be
+ locked to the internal Zaptel timer instead.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term>-L <replaceable class="parameter">loadaverage</replaceable></term>
<listitem>
<para>
diff --git a/channel.c b/channel.c
index fdf2c97c1..717a92de0 100644
--- a/channel.c
+++ b/channel.c
@@ -1976,30 +1976,34 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
f = &ast_null_frame;
}
- /* Run any generator sitting on the channel */
- if (chan->generatordata) {
- /* Mask generator data temporarily and apply. If there is a timing function, it
- will be calling the generator instead */
+ /* Run generator sitting on the line if timing device not available
+ * and synchronous generation of outgoing frames is necessary */
+ if (chan->generatordata && !ast_internal_timing_enabled(chan)) {
void *tmp;
int res;
int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
-
+
if (chan->timingfunc) {
- ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n");
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n");
ast_settimeout(chan, 0, NULL, NULL);
}
+
tmp = chan->generatordata;
chan->generatordata = NULL;
generate = chan->generator->generate;
res = generate(chan, tmp, f->datalen, f->samples);
chan->generatordata = tmp;
if (res) {
- ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
ast_deactivate_generator(chan);
}
+
} else if (f->frametype == AST_FRAME_CNG) {
if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) {
- ast_log(LOG_DEBUG, "Generator got CNG, switching to timed mode\n");
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "Generator got CNG, switching to timed mode\n");
ast_settimeout(chan, 160, generator_force, chan);
}
}
@@ -2027,6 +2031,14 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
return f;
}
+int ast_internal_timing_enabled(struct ast_channel *chan)
+{
+ int ret = option_internal_timing && chan->timingfd > -1;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Internal timing is %s (option_internal_timing=%d chan->timingfd=%d)\n", ret? "enabled": "disabled", option_internal_timing, chan->timingfd);
+ return ret;
+}
+
struct ast_frame *ast_read(struct ast_channel *chan)
{
return __ast_read(chan, 0);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 4ce8a121f..ff0ce2250 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -4699,7 +4699,8 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p)
debug);
}
- ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n");
+ if(!ast_internal_timing_enabled(p->owner))
+ ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n");
if ((m_audio_left < 2) || (m_video_left < 2) || (a_audio_left == 0) || (a_video_left == 0))
ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
diff --git a/doc/asterisk-conf.txt b/doc/asterisk-conf.txt
index 1380291a0..5b22302d0 100644
--- a/doc/asterisk-conf.txt
+++ b/doc/asterisk-conf.txt
@@ -52,6 +52,7 @@ timestamp = yes | no ; Force timestamping on log entries to console (-T)
runuser = asterisk ; User to run asterisk as (-U) NOTE: will require changes to
; directory and device permisions
rungroup = asterisk ; Group to run asterisk as (-G)
+internal_timing = yes | no ; Enable internal timing support (-I)
;These options have no command line equivalent
cache_record_files = yes | no ; Cache record() files in another directory until completion
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 35fe0c020..9cdc280ac 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -1124,6 +1124,16 @@ struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_cha
*/
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state);
+/*!
+ \brief Check if the channel can run in internal timing mode.
+ \param chan The channel to check
+ \return boolean
+
+ This function will return 1 if internal timing is enabled and the timing
+ device is available.
+ */
+int ast_internal_timing_enabled(struct ast_channel *chan);
+
/* Misc. functions below */
/* if fd is a valid descriptor, set *pfd with the descriptor
diff --git a/include/asterisk/options.h b/include/asterisk/options.h
index 03470d217..ba8b8b291 100644
--- a/include/asterisk/options.h
+++ b/include/asterisk/options.h
@@ -101,10 +101,10 @@ enum ast_option_flags {
extern struct ast_flags ast_options;
extern int option_verbose;
-extern int option_debug;
-extern int option_maxcalls;
+extern int option_debug; /*!< Debugging */
+extern int option_maxcalls; /*!< Maximum number of simultaneous channels */
extern double option_maxload;
-
+extern int option_internal_timing; /*!< Flag for internal timing (RTP) */
extern char defaultlanguage[];
extern time_t ast_startuptime;