From ff44ce11cc7d6b254c6c549b1a6c8ddb53b792f2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 13 Apr 2007 16:24:02 +0000 Subject: [PATCH] let unicast mode operate on the native codec if desired git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4925 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- scripts/socket/socket2me/socket2me.c | 76 ++++++++++++++++++++++++---- src/include/switch_ivr.h | 3 +- src/include/switch_types.h | 3 +- src/switch_ivr.c | 73 +++++++++++++++----------- 4 files changed, 115 insertions(+), 40 deletions(-) diff --git a/scripts/socket/socket2me/socket2me.c b/scripts/socket/socket2me/socket2me.c index 013c982ee9..128030c0a3 100644 --- a/scripts/socket/socket2me/socket2me.c +++ b/scripts/socket/socket2me/socket2me.c @@ -42,6 +42,7 @@ #include #include + #define SOCKET2ME_DEBUG 0 #define MAXPENDING 10000 #define RCVBUFSIZE 4198 @@ -178,7 +179,9 @@ void client_run(int client_socket, char *local_ip, int local_port, char *remote_ fax_state_t fax; char tmp[512], fn[512], *file_name = "/tmp/test.tiff"; int send_fax = FALSE; - + int g711 = 0; + int pcmu = 0; + snprintf(sendbuf, sizeof(sendbuf), "connect\n\n"); send(client_socket, sendbuf, strlen(sendbuf), 0); @@ -189,17 +192,32 @@ void client_run(int client_socket, char *local_ip, int local_port, char *remote_ #if SOCKET2ME_DEBUG printf("READ [%s]\n", infobuf); #endif + + if (cheezy_get_var(infobuf, "Channel-Read-Codec-Name", tmp, sizeof(tmp))) { + if (!strcasecmp(tmp, "pcmu")) { + g711 = 1; + pcmu = 1; + } else if (!strcasecmp(tmp, "pcma")) { + g711 = 1; + } + } + + snprintf(sendbuf, sizeof(sendbuf), "sendmsg\n" "call-command: unicast\n" "local_ip: %s\n" "local_port: %d\n" "remote_ip: %s\n" "remote_port: %d\n" - "transport: udp\n\n", + "transport: udp\n" + "%s" + "\n", local_ip, local_port, - remote_ip, remote_port + remote_ip, remote_port, + g711 ? "flags: native\n" : "" ); + if (cheezy_get_var(infobuf, "variable_fax_file_name", fn, sizeof(fn))) { file_name = fn; } @@ -267,8 +285,9 @@ void client_run(int client_socket, char *local_ip, int local_port, char *remote_ for (;;) { struct sockaddr_in local_addr = {0}; int cliAddrLen = sizeof(local_addr); - short audioBuffer[1024], outbuf[1024]; - int tx, bigger; + unsigned char audiobuf[1024], rawbuf[1024], outbuf[1024]; + short *usebuf = NULL; + int tx, tx_bytes, bigger, sample_count; fd_set ready; FD_ZERO(&ready); @@ -297,23 +316,62 @@ void client_run(int client_socket, char *local_ip, int local_port, char *remote_ continue; } - if ((read_bytes = recvfrom(usock, audioBuffer, sizeof(audioBuffer), 0, (struct sockaddr *) &local_addr, &cliAddrLen)) < 0) { + if ((read_bytes = recvfrom(usock, audiobuf, sizeof(audiobuf), 0, (struct sockaddr *) &local_addr, &cliAddrLen)) < 0) { die("recvfrom() failed"); } - fax_rx(&fax, (int16_t *)audioBuffer, read_bytes / 2); + if (g711) { + int i; + short *rp = (short *) rawbuf; + + for (i = 0; i < read_bytes; i++) { + if (pcmu) { + rp[i] = ulaw_to_linear(audiobuf[i]); + } else { + rp[i] = alaw_to_linear(audiobuf[i]); + } + } + usebuf = rp; + sample_count = read_bytes; + } else { + usebuf = (short *) audiobuf; + sample_count = read_bytes / 2; + } + + fax_rx(&fax, usebuf, sample_count); #if SOCKET2ME_DEBUG printf("Handling client %s:%d %d bytes\n", inet_ntoa(local_addr.sin_addr), ntohs(local_addr.sin_port), read_bytes); #endif - if ((tx = fax_tx(&fax, (int16_t *) &outbuf, read_bytes / 2)) < 0) { + + + if ((tx = fax_tx(&fax, (short *)outbuf, sample_count)) < 0) { printf("Fax Error\n"); break; } else if (!tx) { continue; } + + if (g711) { + int i; + short *bp = (short *) outbuf; + for (i = 0; i < tx; i++) { + if (pcmu) { + rawbuf[i] = linear_to_ulaw(bp[i]); + } else { + rawbuf[i] = linear_to_alaw(bp[i]); + } + } + usebuf = (short *) rawbuf; + tx_bytes = tx; + } else { + usebuf = (short *)outbuf; + tx_bytes = tx * 2; + } + + cliAddrLen = sizeof(sendaddr); - if (sendto(usock, outbuf, tx * 2, 0, (struct sockaddr *) &sendaddr, sizeof(sendaddr)) != tx * 2) { + if (sendto(usock, usebuf, tx_bytes, 0, (struct sockaddr *) &sendaddr, sizeof(sendaddr)) != sample_count) { die("sendto() sent a different number of bytes than expected"); } } diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index dde5051185..a66ce41562 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -78,7 +78,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_activate_unicast(switch_core_session_ switch_port_t local_port, char *remote_ip, switch_port_t remote_port, - char *transport); + char *transport, + char *flags); /*! \brief Generate an XML CDR report. diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 5e0cf4a7cc..d3625db285 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -121,7 +121,8 @@ SWITCH_BEGIN_EXTERN_C typedef enum { SUF_NONE = 0, SUF_THREAD_RUNNING = (1 << 0), - SUF_READY = (1 << 1) + SUF_READY = (1 << 1), + SUF_NATIVE = (1 << 2) } switch_unicast_flag_t; typedef enum { diff --git a/src/switch_ivr.c b/src/switch_ivr.c index f41a24b134..5566f55c97 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -140,7 +140,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_deactivate_unicast(switch_core_sessio break; } } - switch_core_codec_destroy(&conninfo->read_codec); + if (conninfo->read_codec.implementation) { + switch_core_codec_destroy(&conninfo->read_codec); + } switch_socket_close(conninfo->socket); } switch_channel_clear_flag(channel, CF_UNICAST); @@ -156,7 +158,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_activate_unicast(switch_core_session_ switch_port_t local_port, char *remote_ip, switch_port_t remote_port, - char *transport) + char *transport, + char *flags) { switch_channel_t *channel; switch_unicast_conninfo_t *conninfo; @@ -186,29 +189,37 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_activate_unicast(switch_core_session_ goto fail; } + if (flags) { + if (strstr(flags, "native")) { + switch_set_flag(conninfo, SUF_NATIVE); + } + } + switch_mutex_init(&conninfo->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); read_codec = switch_core_session_get_read_codec(session); - if (switch_core_codec_init(&conninfo->read_codec, - "L16", - NULL, - read_codec->implementation->samples_per_second, - read_codec->implementation->microseconds_per_frame / 1000, - 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, - "Raw Codec Activation Success L16@%uhz 1 channel %dms\n", - read_codec->implementation->samples_per_second, read_codec->implementation->microseconds_per_frame / 1000); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz 1 channel %dms\n", - read_codec->implementation->samples_per_second, read_codec->implementation->microseconds_per_frame / 1000); - goto fail; + if (!switch_test_flag(conninfo, SUF_NATIVE)) { + if (switch_core_codec_init(&conninfo->read_codec, + "L16", + NULL, + read_codec->implementation->samples_per_second, + read_codec->implementation->microseconds_per_frame / 1000, + 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, + NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, + "Raw Codec Activation Success L16@%uhz 1 channel %dms\n", + read_codec->implementation->samples_per_second, read_codec->implementation->microseconds_per_frame / 1000); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz 1 channel %dms\n", + read_codec->implementation->samples_per_second, read_codec->implementation->microseconds_per_frame / 1000); + goto fail; + } } conninfo->write_frame.data = conninfo->write_frame_data; conninfo->write_frame.buflen = sizeof(conninfo->write_frame_data); - conninfo->write_frame.codec = &conninfo->read_codec; + conninfo->write_frame.codec = switch_test_flag(conninfo, SUF_NATIVE) ? read_codec : &conninfo->read_codec; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "connect %s:%d->%s:%d\n", @@ -307,6 +318,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se char *remote_ip = switch_event_get_header(event, "remote_ip"); char *remote_port = switch_event_get_header(event, "remote_port"); char *transport = switch_event_get_header(event, "transport"); + char *flags = switch_event_get_header(event, "flags"); if (switch_strlen_zero(local_ip)) { local_ip = "127.0.0.1"; @@ -324,7 +336,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se transport = "udp"; } - switch_ivr_activate_unicast(session, local_ip, (switch_port_t)atoi(local_port), remote_ip, (switch_port_t)atoi(remote_port), transport); + switch_ivr_activate_unicast(session, local_ip, (switch_port_t)atoi(local_port), remote_ip, (switch_port_t)atoi(remote_port), transport, flags); } else if (cmd_hash == CMD_HANGUP) { char *cause_name = switch_event_get_header(event, "hangup-cause"); @@ -383,9 +395,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, unicast_thread_launch(conninfo); } } - + if (conninfo) { - switch_size_t len; + switch_size_t len = 0; uint32_t flags = 0; switch_byte_t decoded[SWITCH_RECOMMENDED_BUFFER_SIZE]; uint32_t rate = read_codec->implementation->samples_per_second; @@ -400,14 +412,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, sendbuf = decoded; status = SWITCH_STATUS_SUCCESS; } else { - - status = switch_core_codec_decode( - read_codec, - &conninfo->read_codec, - read_frame->data, - read_frame->datalen, - read_codec->implementation->samples_per_second, - decoded, &dlen, &rate, &flags); + if (switch_test_flag(conninfo, SUF_NATIVE)) { + status = SWITCH_STATUS_NOOP; + } else { + status = switch_core_codec_decode( + read_codec, + &conninfo->read_codec, + read_frame->data, + read_frame->datalen, + read_codec->implementation->samples_per_second, + decoded, &dlen, &rate, &flags); + } switch (status) { case SWITCH_STATUS_NOOP: case SWITCH_STATUS_BREAK: @@ -435,7 +450,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, } } } - + if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) { switch_ivr_parse_event(session, event); switch_channel_event_set_data(switch_core_session_get_channel(session), event);