From bfe2f22b3892529d775f68ed4448ad0c462790a8 Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Fri, 13 Aug 2010 13:37:50 -0400
Subject: [PATCH] add non-blocking reads to mod_sangoma_codec

---
 .../mod_sangoma_codec/mod_sangoma_codec.c     | 88 +++++++++++--------
 1 file changed, 51 insertions(+), 37 deletions(-)

diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c
index 01cb10edb2..add0dbc865 100644
--- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c
+++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c
@@ -126,6 +126,9 @@ struct codec_data {
   	long lastrxseqno;
 	unsigned long rxlost;
 
+	/* discarded silence packets */
+	unsigned long rxdiscarded;
+
 	/* avg Rx time */
 	switch_time_t avgrxus;
 	switch_time_t last_rx_time;
@@ -400,26 +403,31 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec
 	sess->encoder.tx++;
 
 	/* do the reading */
-	memset(&encoded_frame, 0, sizeof(encoded_frame));
-	sres = switch_rtp_zerocopy_read_frame(sess->encoder.rxrtp, &encoded_frame, SWITCH_IO_FLAG_NOBLOCK);
-	if (sres == SWITCH_STATUS_GENERR) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma encoder RTP session: %d\n", sres);
-		return SWITCH_STATUS_FALSE;
-	}
+	for ( ; ; ) {
+		sres = switch_rtp_zerocopy_read_frame(sess->encoder.rxrtp, &encoded_frame, SWITCH_IO_FLAG_NOBLOCK);
+		if (sres == SWITCH_STATUS_GENERR) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma encoder RTP session: %d\n", sres);
+			return SWITCH_STATUS_FALSE;
+		}
 
-	if (0 == encoded_frame.datalen) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No output on Sangoma encoder RTP session.\n");
-		return SWITCH_STATUS_SUCCESS;
-	}
+		if (0 == encoded_frame.datalen) {
+			break;
+		}
 
-	if (encoded_frame.payload != codec->implementation->ianacode
-	    && encoded_frame.payload != IANACODE_CN) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma encoder RTP session, expecting %d\n", 
-				encoded_frame.payload, codec->implementation->ianacode);
-		return SWITCH_STATUS_FALSE;
+		if (encoded_frame.payload != codec->implementation->ianacode
+		    && encoded_frame.payload != IANACODE_CN) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma encoder RTP session, expecting %d\n",
+					encoded_frame.payload, codec->implementation->ianacode);
+			break;
+		}
+
+		if (*encoded_data_len) {
+			sess->encoder.rxdiscarded++;
+		}
+
+		memcpy(encoded_data, encoded_frame.data, encoded_frame.datalen);
+		*encoded_data_len = encoded_frame.datalen;
 	}
-	memcpy(encoded_data, encoded_frame.data, encoded_frame.datalen);
-	*encoded_data_len = encoded_frame.datalen;
 
 	/* update encoding stats */
 	sess->encoder.rx++;
@@ -513,30 +521,34 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec,	/* codec ses
 	sess->decoder.tx++;
 
 	/* do the reading */
-	memset(&ulaw_frame, 0, sizeof(ulaw_frame));
-	sres = switch_rtp_zerocopy_read_frame(sess->decoder.rxrtp, &ulaw_frame, SWITCH_IO_FLAG_NOBLOCK);
-	if (sres == SWITCH_STATUS_GENERR) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma decoder RTP session: %d\n", sres);
-		return SWITCH_STATUS_FALSE;
-	}
+	for ( ; ; ) {
+		sres = switch_rtp_zerocopy_read_frame(sess->decoder.rxrtp, &ulaw_frame, SWITCH_IO_FLAG_NOBLOCK);
+		if (sres == SWITCH_STATUS_GENERR) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma decoder RTP session: %d\n", sres);
+			return SWITCH_STATUS_FALSE;
+		}
 
-	if (0 == ulaw_frame.datalen) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No output on Sangoma decoder RTP session.\n");
-		return SWITCH_STATUS_SUCCESS;
-	}
+		if (0 == ulaw_frame.datalen) {
+			break;
+		}
 
-	if (ulaw_frame.payload != IANA_ULAW
-	    && ulaw_frame.payload != IANACODE_CN) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma decoder RTP session, expecting %d\n", 
-				ulaw_frame.payload, IANA_ULAW);
-		return SWITCH_STATUS_FALSE;
-	}
+		if (ulaw_frame.payload != IANA_ULAW
+		    && ulaw_frame.payload != IANACODE_CN) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma decoder RTP session, expecting %d\n",
+					ulaw_frame.payload, IANA_ULAW);
+			break;
+		}
 
-	/* transcode to linear */
-	for (i = 0; i < ulaw_frame.datalen; i++) {
-		dbuf_linear[i] = ulaw_to_linear(((char *)ulaw_frame.data)[i]);
+		if (*decoded_data_len) {
+			sess->decoder.rxdiscarded++;
+		}
+
+		/* transcode to linear */
+		for (i = 0; i < ulaw_frame.datalen; i++) {
+			dbuf_linear[i] = ulaw_to_linear(((char *)ulaw_frame.data)[i]);
+		}
+		*decoded_data_len = i * 2;
 	}
-	*decoded_data_len = i * 2;
 
 	/* update decoding stats */
 	sess->decoder.rx++;
@@ -708,6 +720,7 @@ SWITCH_STANDARD_API(sangoma_function)
 		if (sess->encoder.rxrtp) {
 			stats = switch_rtp_get_stats(sess->encoder.rxrtp, NULL);
 			stream->write_function(stream, "-- Encoder Inbound Stats --\n");
+			stream->write_function(stream, "Rx Discarded: %lu\n", sess->encoder.rxdiscarded);
 			sangoma_print_stats(stream, &stats->inbound);
 			
 
@@ -719,6 +732,7 @@ SWITCH_STANDARD_API(sangoma_function)
 		if (sess->decoder.rxrtp) {
 			stats = switch_rtp_get_stats(sess->decoder.rxrtp, NULL);
 			stream->write_function(stream, "-- Decoder Inbound Stats --\n");
+			stream->write_function(stream, "Rx Discarded: %lu\n", sess->decoder.rxdiscarded);
 			sangoma_print_stats(stream, &stats->inbound);
 
 			stats = switch_rtp_get_stats(sess->decoder.txrtp, NULL);