Issue #5374 - Enable internal timing of generators (cmantunes)
authorOlle Johansson <oej@edvina.net>
Thu, 30 Mar 2006 06:07:04 +0000 (06:07 +0000)
committerOlle Johansson <oej@edvina.net>
Thu, 30 Mar 2006 06:07:04 +0000 (06:07 +0000)
Thanks everyone involved for hard work, testing and testing!

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@16473 65c4cc65-6c06-0410-ace0-fbb531ad65f3

Makefile
apps/app_milliwatt.c
apps/app_sms.c
asterisk.8
asterisk.c
asterisk.sgml
channel.c
channels/chan_sip.c
doc/asterisk-conf.txt
include/asterisk/channel.h
include/asterisk/options.h

index 4414a76..b4f722c 100644 (file)
--- 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"; \
index 69fc388..27eb9ad 100644 (file)
@@ -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;
index d9b85bf..a607d35 100644 (file)
@@ -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)
index 28ea0ff..b90e342 100644 (file)
@@ -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.
index 9ef3c44..9f3b234 100644 (file)
@@ -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;
index 663a816..ff257ff 100644 (file)
@@ -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>
                </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>
index fdf2c97..717a92d 100644 (file)
--- 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);
index 4ce8a12..ff0ce22 100644 (file)
@@ -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");
index 1380291..5b22302 100644 (file)
@@ -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
index 35fe0c0..9cdc280 100644 (file)
@@ -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
index 03470d2..ba8b8b2 100644 (file)
@@ -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;