[asterisk-commits] irroot: branch irroot/distrotech-customers-10 r339461 - /team/irroot/distrote...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Oct 5 01:23:29 CDT 2011


Author: irroot
Date: Wed Oct  5 01:23:24 2011
New Revision: 339461

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=339461
Log:
Add generic faxdetect framehook to res_fax

Added func FAXOPT(faxdetect)=yes,cng,t38[,timeout]/no
to enable dialplan faxdetect allowing more flexibility.

as soon as a fax tone is detected the framehook is removed.
there is a penalty involved in running this framehook on
non G711 channels as they will be transcoded.

CNG tone is suppresed using the SQUELCH flag to allow
WaitForNoise to be run on the channel to detect Voice.

This patch also fixes a race condition ending in segfault
the caps in the gateway must not be changed till the sesion
is destroyed.

(Closes issue ASTERISK-18569)
Reported by: Myself
Reviewed by: Matthew Nicholson, Kevin Fleming

Review: https://reviewboard.asterisk.org/r/1116/

Modified:
    team/irroot/distrotech-customers-10/res/res_fax.c

Modified: team/irroot/distrotech-customers-10/res/res_fax.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/distrotech-customers-10/res/res_fax.c?view=diff&rev=339461&r1=339460&r2=339461
==============================================================================
--- team/irroot/distrotech-customers-10/res/res_fax.c (original)
+++ team/irroot/distrotech-customers-10/res/res_fax.c Wed Oct  5 01:23:24 2011
@@ -193,7 +193,7 @@
 						<para>R/W T38 fax gateway, with optional fax activity timeout in seconds (yes[,timeout]/no)</para>
 					</enum>
 					<enum name="faxdetect">
-						<para>R/W Enable FAX detect with optional timeout in seconds (yes[,timeout]/no)</para>
+						<para>R/W Enable FAX detect with optional timeout in seconds (yes,t38,cng[,timeout]/no)</para>
 					</enum>
 					<enum name="pages">
 						<para>R/O Number of pages transferred.</para>
@@ -281,11 +281,16 @@
 	struct ast_dsp *dsp;
 	/*! \brief original audio formats */
 	struct ast_format orig_format;
-	/*! \brief Noise limit to end faxdetect */
-	int noiselim;
 	/*! \brief fax session details */
 	struct ast_fax_session_details *details;
+	/*! \brief mode */
+	int flags;
 };
+
+/*! \brief FAX Detect flags */
+#define FAX_DETECT_MODE_CNG	(1 << 0)
+#define FAX_DETECT_MODE_T38	(1 << 1)
+#define	FAX_DETECT_MODE_BOTH	(FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)
 
 static int fax_logger_level = -1;
 
@@ -846,6 +851,9 @@
 	}
 
 	if (s->details) {
+		if (s->details->caps & AST_FAX_TECH_GATEWAY) {
+			s->details->caps &= ~AST_FAX_TECH_GATEWAY;
+		}
 		ao2_ref(s->details, -1);
 	}
 	
@@ -1724,7 +1732,7 @@
 	ast_string_field_set(details, error, "INIT_ERROR");
 	set_channel_variables(chan, details);
 
-	if ((details->caps & AST_FAX_TECH_GATEWAY) && (details->gateway_id > 0)) {
+	if (details->gateway_id > 0) {
 		ast_string_field_set(details, resultstr, "can't receive a fax on a channel with a T.38 gateway");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
@@ -2194,7 +2202,7 @@
 	ast_string_field_set(details, error, "INIT_ERROR");
 	set_channel_variables(chan, details);
 
-	if ((details->caps & AST_FAX_TECH_GATEWAY) && (details->gateway_id > 0)) {
+	if (details->gateway_id > 0) {
 		ast_string_field_set(details, resultstr, "can't send a fax on a channel with a T.38 gateway");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "executing SendFAX on a channel with a T.38 Gateway is not supported\n");
@@ -2451,7 +2459,6 @@
 	if (gateway->s) {
 		fax_session_release(gateway->s, gateway->token);
 		gateway->token = NULL;
-		gateway->s->details->caps &= ~AST_FAX_TECH_GATEWAY;
 
 		ao2_lock(faxregistry.container);
 		ao2_unlink(faxregistry.container, gateway->s);
@@ -3157,18 +3164,17 @@
 /*! \brief Create a new fax detect object.
  * \param chan the channel attaching to
  * \param timeout remove framehook in this time if set
- * \param noiselim end faxdetect when noiselim ms of noise is detected
- * \param dsp_detect_flag dsp faxmode detect flags
+ * \param flags required options
  * \return NULL or a fax gateway object
  */
-static struct fax_detect *fax_detect_new(struct ast_channel *chan, int timeout, int noiselim, int dsp_detect_flag)
+static struct fax_detect *fax_detect_new(struct ast_channel *chan, int timeout, int flags)
 {
 	struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
 	if (!faxdetect) {
 		return NULL;
 	}
 
-	faxdetect->noiselim = noiselim;
+	faxdetect->flags = flags;
 
 	if (timeout) {
 		faxdetect->timeout_start = ast_tvnow();
@@ -3177,15 +3183,18 @@
 		faxdetect->timeout_start.tv_usec = 0;
 	}
 
-	faxdetect->dsp = ast_dsp_new();
-	if (!faxdetect->dsp) {
-		ao2_ref(faxdetect, -1);
-		return NULL;
-	}
-
-	ast_dsp_set_features(faxdetect->dsp, DSP_FEATURE_FAX_DETECT);
-	ast_dsp_set_faxmode(faxdetect->dsp, dsp_detect_flag | DSP_FAXMODE_DETECT_SQUELCH);
-	ast_dsp_set_threshold(faxdetect->dsp, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
+	if (faxdetect->flags & FAX_DETECT_MODE_CNG) {
+		faxdetect->dsp = ast_dsp_new();
+		if (!faxdetect->dsp) {
+			ao2_ref(faxdetect, -1);
+			return NULL;
+		}
+		ast_dsp_set_features(faxdetect->dsp, DSP_FEATURE_FAX_DETECT);
+		ast_dsp_set_faxmode(faxdetect->dsp, DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_SQUELCH);
+	} else {
+		faxdetect->dsp = NULL;
+	}
+
 	return faxdetect;
 }
 
@@ -3213,7 +3222,6 @@
 	struct ast_fax_session_details *details;
 	struct ast_control_t38_parameters *control_params;
 	struct ast_channel *peer;
-	int dspnoise;
 	int result = 0;
 
 	details = faxdetect->details;
@@ -3261,9 +3269,13 @@
 		return f;
 	}
 
-	/* only handle VOICE/DTMF and CONTROL frames*/
+	/* only handle VOICE and CONTROL frames*/
 	switch (f->frametype) {
 	case AST_FRAME_VOICE:
+		/* we have no DSP this means we not detecting CNG */
+		if (!faxdetect->dsp) {
+			break;
+		}
 		/* We can only process some formats*/
 		switch (f->subclass.format.id) {
 			case AST_FORMAT_SLINEAR:
@@ -3275,12 +3287,8 @@
 		}
 		break;
 	case AST_FRAME_CONTROL:
-		if (f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
-			break;
-		}
-		return f;
-	case AST_FRAME_DTMF:
-		if ((f->subclass.integer == 'f') || (f->subclass.integer == 'e')) {
+		if ((f->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
+		    (faxdetect->flags & FAX_DETECT_MODE_T38)) {
 			break;
 		}
 		return f;
@@ -3292,11 +3300,6 @@
 		f = ast_dsp_process(chan, faxdetect->dsp, f);
 		if (f->frametype == AST_FRAME_DTMF) {
 			result = f->subclass.integer;
-		} else if ((f->frametype == AST_FRAME_VOICE) && (faxdetect->noiselim > 0)) {
-			ast_dsp_noise(faxdetect->dsp, f, &dspnoise);
-			if (dspnoise > faxdetect->noiselim) {
-				result = 'n';
-			}
 		}
 	} else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen == sizeof(struct ast_control_t38_parameters))) {
 		control_params = f->data.ptr;
@@ -3308,8 +3311,6 @@
 		default:
 			break;
 		}
-	} else if (f->frametype == AST_FRAME_DTMF) {
-		result = f->subclass.integer;
 	}
 
 	if (result) {
@@ -3331,8 +3332,8 @@
 				f = &ast_null_frame;
 			} else {
 				ast_channel_lock(chan);
-				ast_log(LOG_NOTICE, "FAX %s detected but no fax extension\n",
-					(result == 'f') ? "CNG" : "T38");
+				ast_log(LOG_NOTICE, "FAX %s detected but no fax extension in context (%s)\n",
+					(result == 'f') ? "CNG" : "T38", target_context);
 			}
 		}
 		ast_framehook_detach(chan, details->faxdetect_id);
@@ -3345,12 +3346,11 @@
 /*! \brief Attach a faxdetect framehook object to a channel.
  * \param chan the channel to attach to
  * \param timeout remove framehook in this time if set
- * \param noiselim end faxdetect when noiselim ms of noise is detected
- * \param dsp_detect_flag dsp faxmode detect flags
  * \return the faxdetect structure or NULL on error
+ * \param flags required options
  * \retval -1 error
  */
-static struct fax_detect* fax_detect_attach(struct ast_channel *chan, int timeout, int noiselim, int dsp_detect_flags)
+static int fax_detect_attach(struct ast_channel *chan, int timeout, int flags)
 {
 	struct fax_detect *faxdetect;
 	struct ast_fax_session_details *details;
@@ -3362,14 +3362,14 @@
 
 	if (!(details = find_or_create_details(chan))) {
 		ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
-		return NULL;
+		return -1;
 	}
 
 	/* set up the frame hook*/
-	faxdetect = fax_detect_new(chan, timeout, noiselim, dsp_detect_flags);
+	faxdetect = fax_detect_new(chan, timeout, flags);
 	if (!faxdetect) {
 		ao2_ref(details, -1);
-		return NULL;
+		return -1;
 	}
 
 	fr_hook.data = faxdetect;
@@ -3380,12 +3380,9 @@
 
 	if (details->faxdetect_id < 0) {
 		ao2_ref(faxdetect, -1);
-		return NULL;
-	}
-
-	/* return it with ref held in framhook and return*/
-	ao2_ref(faxdetect, 1);
-	return faxdetect;
+	}
+
+	return details->faxdetect_id;
 }
 
 /*! \brief hash callback for ao2 */
@@ -3906,27 +3903,38 @@
 		const char *val = ast_skip_blanks(value);
 		char *timeout = strchr(val, ',');
 		unsigned int fdtimeout = 0;
-		struct fax_detect *faxdetect;
+		int flags;
+		int faxdetect;
 
 		if (timeout) {
 			*timeout++ = '\0';
 		}
 
-		if (ast_true(val)) {
+		if (ast_true(val) || !strcasecmp(val, "t38") || !strcasecmp(val, "cng")) {
 			if (details->faxdetect_id < 0) {
 				if (timeout && (sscanf(timeout, "%u", &fdtimeout) == 1)) {
-					fdtimeout = fdtimeout * 1000;
+					if (fdtimeout > 0) {
+						fdtimeout = fdtimeout * 1000;
+					} else {
+						ast_log(LOG_WARNING, "Timeout cannot be negative ignoring timeout\n");
+					}
 				}
 
-				faxdetect = fax_detect_attach(chan, fdtimeout, 0, DSP_FAXMODE_DETECT_CNG);
-
-				if (faxdetect && (details->faxdetect_id >= 0)) {
-					ast_debug(1, "Attached FAX detect to channel %s.\n", chan->name);
+				if (!strcasecmp(val, "t38")) {
+					flags = FAX_DETECT_MODE_T38;
+				} else if (!strcasecmp(val, "cng")) {
+					flags = FAX_DETECT_MODE_CNG;
 				} else {
+					flags = FAX_DETECT_MODE_BOTH;
+				}
+
+				faxdetect = fax_detect_attach(chan, fdtimeout, flags);
+				if (faxdetect < 0) {
 					ast_log(LOG_ERROR, "Error attaching FAX detect to channel %s.\n", chan->name);
 					res = -1;
+				} else {
+					ast_debug(1, "Attached FAX detect to channel %s.\n", chan->name);
 				}
-				ao2_ref(faxdetect, -1);
 			} else {
 				ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", chan->name);
 			}




More information about the asterisk-commits mailing list