[Freeswitch-svn] [commit] r7599 - freeswitch/trunk/src

Freeswitch SVN anthm at freeswitch.org
Tue Feb 12 19:32:09 EST 2008


Author: anthm
Date: Tue Feb 12 19:32:09 2008
New Revision: 7599

Modified:
   freeswitch/trunk/src/switch_ivr_async.c
   freeswitch/trunk/src/switch_rtp.c

Log:
fix inband DTMF generation issue

Modified: freeswitch/trunk/src/switch_ivr_async.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_async.c	(original)
+++ freeswitch/trunk/src/switch_ivr_async.c	Tue Feb 12 19:32:09 2008
@@ -878,9 +878,11 @@
 typedef struct {
 	switch_core_session_t *session;
 	teletone_generation_session_t ts;
+	switch_queue_t *digit_queue;
     switch_buffer_t *audio_buffer;
 	switch_mutex_t *mutex;
 	int read;
+	int ready;
 } switch_inband_dtmf_generate_t;
 
 static int teletone_dtmf_generate_handler(teletone_generation_session_t * ts, teletone_tone_map_t * map)
@@ -902,22 +904,36 @@
 {
     switch_channel_t *channel = switch_core_session_get_channel(session);
     switch_media_bug_t *bug = switch_channel_get_private(channel, "dtmf_generate");
-    
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
+
     if (bug) {
         switch_inband_dtmf_generate_t *pvt = (switch_inband_dtmf_generate_t *) switch_core_media_bug_get_user_data(bug);
         
         if (pvt) {
-			char buf[2] = "";
 			switch_mutex_lock(pvt->mutex);
-			buf[0] = dtmf->digit;
-			teletone_run(&pvt->ts, buf);
+			if (pvt->ready) {
+				switch_dtmf_t *dt = NULL;
+				switch_zmalloc(dt, sizeof(*dt));
+				*dt = *dtmf;
+				if (switch_queue_trypush(pvt->digit_queue, dt) == SWITCH_STATUS_SUCCESS) {
+					dt = NULL;
+					/* 
+					   SWITCH_STATUS_FALSE indicates pretend there never was a DTMF
+					   since we will be generating it inband now.
+					*/
+					status = SWITCH_STATUS_FALSE;
+				} else {
+					free(dt);
+				}
+			}
 			switch_mutex_unlock(pvt->mutex);
-			return SWITCH_STATUS_FALSE;
 		}
 	}
-	return SWITCH_STATUS_SUCCESS;
+
+	return status;
 }
 
+
 static switch_bool_t inband_dtmf_generate_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
 {
 	switch_inband_dtmf_generate_t *pvt = (switch_inband_dtmf_generate_t *) user_data;
@@ -929,37 +945,63 @@
 	switch (type) {
 	case SWITCH_ABC_TYPE_INIT:
 		{
+			switch_queue_create(&pvt->digit_queue, 100, switch_core_session_get_pool(pvt->session));
 			switch_buffer_create_dynamic(&pvt->audio_buffer, 512, 1024, 0);
 			teletone_init_session(&pvt->ts, 0, teletone_dtmf_generate_handler, pvt->audio_buffer);
 			pvt->ts.rate = read_codec->implementation->actual_samples_per_second;
 			pvt->ts.channels = 1;
 			switch_mutex_init(&pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(pvt->session));
 			switch_core_event_hook_add_recv_dtmf(pvt->session, generate_on_dtmf);
+			switch_mutex_lock(pvt->mutex);
+			pvt->ready = 1;
+			switch_mutex_unlock(pvt->mutex);
 		}
 		break;
 	case SWITCH_ABC_TYPE_CLOSE:
 		{
+			switch_mutex_lock(pvt->mutex);
+			pvt->ready = 0;
+			switch_core_event_hook_remove_recv_dtmf(pvt->session, generate_on_dtmf);
 			switch_buffer_destroy(&pvt->audio_buffer);
 			teletone_destroy_session(&pvt->ts);
-			switch_core_event_hook_remove_recv_dtmf(pvt->session, generate_on_dtmf);
+			switch_mutex_unlock(pvt->mutex);
 		}
 		break;
 	case SWITCH_ABC_TYPE_READ_REPLACE:
 	case SWITCH_ABC_TYPE_WRITE_REPLACE:
 		{
 			switch_size_t bytes;
+			void *pop;
+
 			switch_mutex_lock(pvt->mutex);
+
+			if (!pvt->ready) {
+				switch_mutex_unlock(pvt->mutex);
+                return SWITCH_FALSE;
+			}
+
 			if (pvt->read) {
 				frame = switch_core_media_bug_get_read_replace_frame(bug);
 			} else {
 				frame = switch_core_media_bug_get_write_replace_frame(bug);
 			}
+			
+			while (switch_queue_trypop(pvt->digit_queue, &pop) == SWITCH_STATUS_SUCCESS) {
+				switch_dtmf_t *dtmf = (switch_dtmf_t *) pop;
+				char buf[2] = "";
+			
+				buf[0] = dtmf->digit;
+				pvt->ts.duration = dtmf->duration;
+				teletone_run(&pvt->ts, buf);
+			}
+			
 			if (switch_buffer_inuse(pvt->audio_buffer) && (bytes = switch_buffer_read(pvt->audio_buffer, frame->data, frame->datalen))) {
 				if (bytes < frame->datalen) {
 					switch_byte_t *dp = frame->data;
 					memset(dp + bytes, 0, frame->datalen - bytes);
 				}
 			}
+
 			if (pvt->read) {
 				switch_core_media_bug_set_read_replace_frame(bug, frame);
 			} else {

Modified: freeswitch/trunk/src/switch_rtp.c
==============================================================================
--- freeswitch/trunk/src/switch_rtp.c	(original)
+++ freeswitch/trunk/src/switch_rtp.c	Tue Feb 12 19:32:09 2008
@@ -1038,6 +1038,8 @@
 	READ_INC(rtp_session);
 
 	while (switch_rtp_ready(rtp_session)) {
+		int do_cng = 0;
+
 		bytes = sizeof(rtp_msg_t);
 		status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock, 0, (void *) &rtp_session->recv_msg, &bytes);
 		
@@ -1102,7 +1104,64 @@
 			}			
 		}
 
-		if (!bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BREAK)) {
+
+		/* RFC2833 ... like all RFC RE: VoIP, guarenteed to drive you to insanity! 
+		   We know the real rules here, but if we enforce them, it's an interop nightmare so,
+		   we put up with as much as we can so we don't have to deal with being punished for
+		   doing it right. Nice guys finish last!
+		 */
+		if (bytes && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_msg.header.pt == rtp_session->te) {
+			unsigned char *packet = (unsigned char *) rtp_session->recv_msg.body;
+			int end = packet[1] & 0x80 ? 1 : 0;
+			uint16_t duration = (packet[2] << 8) + packet[3];
+			char key = switch_rfc2833_to_char(packet[0]);
+			uint16_t in_digit_seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
+			
+			if (in_digit_seq > rtp_session->dtmf_data.in_digit_seq) {
+				uint32_t ts = htonl(rtp_session->recv_msg.header.ts);
+				//int m = rtp_session->recv_msg.header.m;
+
+				rtp_session->dtmf_data.in_digit_seq = in_digit_seq;
+				
+				//printf("%c %u %u %u\n", key, in_digit_seq, ts, duration);
+
+				if (rtp_session->dtmf_data.last_duration > duration && ts == rtp_session->dtmf_data.in_digit_ts) {
+					rtp_session->dtmf_data.flip++;
+				}
+
+				if (end) {
+					if (rtp_session->dtmf_data.in_digit_ts) {
+						switch_dtmf_t dtmf = { key, duration };
+					
+						if (ts > rtp_session->dtmf_data.in_digit_ts) {
+							dtmf.duration += (ts - rtp_session->dtmf_data.in_digit_ts);
+						}
+						if (rtp_session->dtmf_data.flip) {
+							dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF;
+							rtp_session->dtmf_data.flip = 0;
+							//printf("you're welcome!\n");
+						}
+
+						//printf("done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n", 
+						//dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration);
+						switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
+						switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK);
+						rtp_session->dtmf_data.last_digit = rtp_session->dtmf_data.first_digit;
+					}
+					rtp_session->dtmf_data.in_digit_ts = 0;
+				} else if (!rtp_session->dtmf_data.in_digit_ts) {
+					rtp_session->dtmf_data.in_digit_ts = ts;
+					rtp_session->dtmf_data.first_digit = key;
+				} 
+				
+				rtp_session->dtmf_data.last_duration = duration;
+
+			}
+
+			do_cng = 1;
+		}
+		
+		if (do_cng || (!bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BREAK))) {
 			switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK);
 
 			memset(&rtp_session->recv_msg.body, 0, 2);
@@ -1239,69 +1298,15 @@
 
 		rtp_session->rpayload = (switch_payload_t) rtp_session->recv_msg.header.pt;
 
-		/* RFC2833 ... like all RFC RE: VoIP, guarenteed to drive you to insanity! 
-		   We know the real rules here, but if we enforce them, it's an interop nightmare so,
-		   we put up with as much as we can so we don't have to deal with being punished for
-		   doing it right. Nice guys finish last!
-		 */
-		if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_msg.header.pt == rtp_session->te) {
-			unsigned char *packet = (unsigned char *) rtp_session->recv_msg.body;
-			int end = packet[1] & 0x80 ? 1 : 0;
-			uint16_t duration = (packet[2] << 8) + packet[3];
-			char key = switch_rfc2833_to_char(packet[0]);
-			uint16_t in_digit_seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
-			
-			if (in_digit_seq > rtp_session->dtmf_data.in_digit_seq) {
-				uint32_t ts = htonl(rtp_session->recv_msg.header.ts);
-				//int m = rtp_session->recv_msg.header.m;
-
-				rtp_session->dtmf_data.in_digit_seq = in_digit_seq;
-				
-				//printf("%c %u %u %u\n", key, in_digit_seq, ts, duration);
-
-				if (rtp_session->dtmf_data.last_duration > duration && ts == rtp_session->dtmf_data.in_digit_ts) {
-					rtp_session->dtmf_data.flip++;
-				}
-
-				if (end) {
-					if (rtp_session->dtmf_data.in_digit_ts) {
-						switch_dtmf_t dtmf = { key, duration };
-					
-						if (ts > rtp_session->dtmf_data.in_digit_ts) {
-							dtmf.duration += (ts - rtp_session->dtmf_data.in_digit_ts);
-						}
-						if (rtp_session->dtmf_data.flip) {
-							dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF;
-							rtp_session->dtmf_data.flip = 0;
-							//printf("you're welcome!\n");
-						}
-
-						//printf("done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n", 
-						//dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration);
-						switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
-						switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK);
-						rtp_session->dtmf_data.last_digit = rtp_session->dtmf_data.first_digit;
-					}
-					rtp_session->dtmf_data.in_digit_ts = 0;
-				} else if (!rtp_session->dtmf_data.in_digit_ts) {
-					rtp_session->dtmf_data.in_digit_ts = ts;
-					rtp_session->dtmf_data.first_digit = key;
-				} 
-				
-				rtp_session->dtmf_data.last_duration = duration;
-
-			}
-			goto do_continue;
-		}
 		break;
 
 	do_continue:
 		
 		if (rtp_session->ms_per_packet) {
-            switch_yield((rtp_session->ms_per_packet / 1000) * 750);
-        } else {
-            switch_yield(1000);
-        }
+			switch_yield((rtp_session->ms_per_packet / 1000) * 750);
+		} else {
+			switch_yield(1000);
+		}
 	}
 
 	*payload_type = (switch_payload_t) rtp_session->recv_msg.header.pt;
@@ -1437,7 +1442,7 @@
 	}
 
 	bytes = rtp_common_read(rtp_session, &frame->payload, &frame->flags);
-	
+
 	frame->data = rtp_session->recv_msg.body;
 	frame->packet = &rtp_session->recv_msg;
 	frame->packetlen = bytes;



More information about the Freeswitch-svn mailing list