gather 2833 into RTP core and a few tweaks

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@1351 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2006-05-04 17:51:53 +00:00
parent 81c4e9f959
commit 23d6224dab
8 changed files with 304 additions and 232 deletions

View File

@ -228,6 +228,38 @@ SWITCH_DECLARE(void) switch_rtp_set_invald_handler(switch_rtp_t *rtp_session, sw
*/
SWITCH_DECLARE(switch_status_t) switch_rtp_read(switch_rtp_t *rtp_session, void *data, uint32_t *datalen, switch_payload_t *payload_type, switch_frame_flag_t *flags);
/*!
\brief Queue RFC2833 DTMF data into an RTP Session
\param rtp_session the rtp session to use
\param digits the digit string to queue
\param duration the duration of the dtmf
*/
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_session, char *digits, uint32_t duration);
/*!
\brief Test for presence of DTMF on a given RTP session
\param rtp_session session to test
\return number of digits in the queue
*/
SWITCH_DECLARE(switch_size_t) switch_rtp_has_dtmf(switch_rtp_t *rtp_session);
/*!
\brief Queue DTMF on a given RTP session
\param rtp_session RTP session to queue DTMF to
\param dtmf string of digits to queue
\return SWITCH_STATUS_SUCCESS if successful
*/
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_dtmf(switch_rtp_t *rtp_session, char *dtmf);
/*!
\brief Retrieve DTMF digits from a given RTP session
\param rtp_session RTP session to retrieve digits from
\param dtmf buffer to write dtmf to
\param len max size in bytes of the buffer
\return number of bytes read into the buffer
*/
SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, char *dtmf, switch_size_t len);
/*!
\brief Read data from a given RTP session without copying
\param rtp_session the RTP session to read from
@ -237,7 +269,11 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_read(switch_rtp_t *rtp_session, void
\param flags flags
\return the number of bytes read
*/
SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read(switch_rtp_t *rtp_session, void **data, uint32_t *datalen, switch_payload_t *payload_type, switch_frame_flag_t *flags);
SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read(switch_rtp_t *rtp_session,
void **data,
uint32_t *datalen,
switch_payload_t *payload_type,
switch_frame_flag_t *flags);
/*!
\brief Read data from a given RTP session without copying

View File

@ -517,6 +517,8 @@ typedef enum {
SWITCH_EVENT_TALK - Talking Detected
SWITCH_EVENT_NOTALK - Not Talking Detected
SWITCH_EVENT_SESSION_CRASH - Session Crashed
SWITCH_EVENT_MODULE_LOAD - Module was loaded
SWITCH_EVENT_DTMF - DTMF was sent
SWITCH_EVENT_ALL - All events at once
</pre>
@ -543,6 +545,7 @@ typedef enum {
SWITCH_EVENT_NOTALK,
SWITCH_EVENT_SESSION_CRASH,
SWITCH_EVENT_MODULE_LOAD,
SWITCH_EVENT_DTMF,
SWITCH_EVENT_ALL
} switch_event_types_t;

View File

@ -85,6 +85,13 @@ SWITCH_DECLARE(char) switch_rfc2833_to_char(int event);
*/
SWITCH_DECLARE(unsigned char) switch_char_to_rfc2833(char key);
/*!
\brief determine if a character is a valid DTMF key
\param key the key to test
\return TRUE or FALSE
*/
#define is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42)
/*!
\brief Duplicate a string
*/

View File

@ -124,18 +124,9 @@ struct private_object {
char *remote_user;
unsigned int cand_id;
unsigned int desc_id;
char last_digit;
unsigned int dc;
time_t last_digit_time;
switch_queue_t *dtmf_queue;
char out_digit;
unsigned char out_digit_packet[4];
unsigned int out_digit_sofar;
unsigned int out_digit_dur;
uint16_t out_digit_seq;
int32_t timestamp_send;
int32_t timestamp_recv;
int32_t timestamp_dtmf;
uint32_t last_read;
char *codec_name;
switch_payload_t codec_num;
@ -718,11 +709,14 @@ static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *d
assert(tech_pvt != NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF [%s]\n", dtmf);
snprintf(digits, sizeof(digits), "+%s\n", dtmf);
ldl_handle_send_msg(tech_pvt->profile->handle, tech_pvt->recip, NULL, digits);
//snprintf(digits, sizeof(digits), "+%s\n", dtmf);
//ldl_handle_send_msg(tech_pvt->profile->handle, tech_pvt->recip, NULL, digits);
return SWITCH_STATUS_SUCCESS;
return switch_rtp_queue_rfc2833(tech_pvt->rtp_session,
digits,
100 * (tech_pvt->read_codec.implementation->samples_per_second / 1000));
//return SWITCH_STATUS_SUCCESS;
}
static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout,
@ -769,41 +763,16 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
return SWITCH_STATUS_BREAK;
}
/* RFC2833 ... TBD try harder to honor the duration etc.*/
if (payload == 101) {
unsigned char *packet = tech_pvt->read_frame.data;
int end = packet[1]&0x80;
int duration = (packet[2]<<8) + packet[3];
char key = switch_rfc2833_to_char(packet[0]);
/* SHEESH.... Curse you RFC2833 inventors!!!!*/
if ((time(NULL) - tech_pvt->last_digit_time) > 2) {
tech_pvt->last_digit = 0;
tech_pvt->dc = 0;
}
if (duration && end) {
if (key != tech_pvt->last_digit) {
char digit_str[] = {key, 0};
time(&tech_pvt->last_digit_time);
switch_channel_queue_dtmf(channel, digit_str);
switch_set_flag(tech_pvt, TFLAG_DTMF);
}
if (++tech_pvt->dc >= 3) {
tech_pvt->last_digit = 0;
tech_pvt->dc = 0;
}
tech_pvt->last_digit = key;
} else {
tech_pvt->last_digit = 0;
tech_pvt->dc = 0;
}
}
if (switch_test_flag(&tech_pvt->read_frame, SFF_CNG)) {
tech_pvt->read_frame.datalen = tech_pvt->last_read ? tech_pvt->last_read : tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
}
if (switch_rtp_has_dtmf(tech_pvt->rtp_session)) {
char dtmf[128];
switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, dtmf, sizeof(dtmf));
switch_channel_queue_dtmf(channel, dtmf);
}
if (tech_pvt->read_frame.datalen > 0) {
bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
frames = (tech_pvt->read_frame.datalen / bytes);
@ -867,66 +836,6 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
frames = ((int) frame->datalen / bytes);
samples = frames * tech_pvt->read_codec.implementation->samples_per_frame;
if (tech_pvt->out_digit_dur > 0) {
int x, ts, loops = 1, duration;
tech_pvt->out_digit_sofar += samples;
if (tech_pvt->out_digit_sofar >= tech_pvt->out_digit_dur) {
duration = tech_pvt->out_digit_dur;
tech_pvt->out_digit_packet[1] |= 0x80;
tech_pvt->out_digit_dur = 0;
loops = 3;
} else {
duration = tech_pvt->out_digit_sofar;
}
ts = tech_pvt->timestamp_dtmf += samples;
tech_pvt->out_digit_packet[2] = (unsigned char) (duration >> 8);
tech_pvt->out_digit_packet[3] = (unsigned char) duration;
for (x = 0; x < loops; x++) {
switch_rtp_write_manual(tech_pvt->rtp_session, tech_pvt->out_digit_packet, 4, 0, 101, ts, tech_pvt->out_digit_seq, &frame->flags);
/*
printf("Send %s packet for [%c] ts=%d sofar=%u dur=%d\n", loops == 1 ? "middle" : "end", tech_pvt->out_digit, ts,
tech_pvt->out_digit_sofar, duration);
*/
}
}
if (!tech_pvt->out_digit_dur && tech_pvt->dtmf_queue && switch_queue_size(tech_pvt->dtmf_queue)) {
void *pop;
if (switch_queue_trypop(tech_pvt->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
int x, ts;
struct rfc2833_digit *rdigit = pop;
memset(tech_pvt->out_digit_packet, 0, 4);
tech_pvt->out_digit_sofar = 0;
tech_pvt->out_digit_dur = rdigit->duration;
tech_pvt->out_digit = rdigit->digit;
tech_pvt->out_digit_packet[0] = (unsigned char)switch_char_to_rfc2833(rdigit->digit);
tech_pvt->out_digit_packet[1] = 7;
ts = tech_pvt->timestamp_dtmf += samples;
tech_pvt->out_digit_seq++;
for (x = 0; x < 3; x++) {
switch_rtp_write_manual(tech_pvt->rtp_session, tech_pvt->out_digit_packet, 4, 1, 101, ts, tech_pvt->out_digit_seq, &frame->flags);
/*
printf("Send start packet for [%c] ts=%d sofar=%u dur=%d\n", tech_pvt->out_digit, ts,
tech_pvt->out_digit_sofar, 0);
*/
}
free(rdigit);
}
}
//printf("%s send %d bytes %d samples in %d frames ts=%d\n", switch_channel_get_name(channel), frame->datalen, samples, frames, tech_pvt->timestamp_send);
if (switch_rtp_write_frame(tech_pvt->rtp_session, frame, samples) < 0) {

View File

@ -108,7 +108,6 @@ struct private_object {
int tid;
int32_t timestamp_send;
int32_t timestamp_recv;
int32_t timestamp_dtmf;
int payload_num;
switch_rtp_t *rtp_session;
struct osip_rfc3264 *sdp_config;
@ -120,24 +119,12 @@ struct private_object {
switch_port_t local_sdp_audio_port;
char call_id[50];
int ssrc;
char last_digit;
unsigned int dc;
time_t last_digit_time;
switch_queue_t *dtmf_queue;
char out_digit;
switch_time_t last_read;
unsigned char out_digit_packet[4];
unsigned int out_digit_sofar;
unsigned int out_digit_dur;
uint16_t out_digit_seq;
char *realm;
};
struct rfc2833_digit {
char digit;
int duration;
};
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan)
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_extrtpip, globals.extrtpip)
@ -642,34 +629,10 @@ static switch_status_t exosip_read_frame(switch_core_session_t *session, switch_
return SWITCH_STATUS_BREAK;
}
/* RFC2833 ... TBD try harder to honor the duration etc.*/
if (payload == 101) {
unsigned char *packet = tech_pvt->read_frame.data;
int end = packet[1]&0x80;
int duration = (packet[2]<<8) + packet[3];
char key = switch_rfc2833_to_char(packet[0]);
/* SHEESH.... Curse you RFC2833 inventors!!!!*/
if ((time(NULL) - tech_pvt->last_digit_time) > 2) {
tech_pvt->last_digit = 0;
tech_pvt->dc = 0;
}
if (duration && end) {
if (key != tech_pvt->last_digit) {
char digit_str[] = {key, 0};
time(&tech_pvt->last_digit_time);
switch_channel_queue_dtmf(channel, digit_str);
}
if (++tech_pvt->dc >= 3) {
tech_pvt->last_digit = 0;
tech_pvt->dc = 0;
}
tech_pvt->last_digit = key;
} else {
tech_pvt->last_digit = 0;
tech_pvt->dc = 0;
}
if (switch_rtp_has_dtmf(tech_pvt->rtp_session)) {
char dtmf[128];
switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, dtmf, sizeof(dtmf));
switch_channel_queue_dtmf(channel, dtmf);
}
@ -740,67 +703,6 @@ static switch_status_t exosip_write_frame(switch_core_session_t *session, switch
}
if (tech_pvt->out_digit_dur > 0) {
int x, ts, loops = 1, duration;
tech_pvt->out_digit_sofar += samples;
if (tech_pvt->out_digit_sofar >= tech_pvt->out_digit_dur) {
duration = tech_pvt->out_digit_dur;
tech_pvt->out_digit_packet[1] |= 0x80;
tech_pvt->out_digit_dur = 0;
loops = 3;
} else {
duration = tech_pvt->out_digit_sofar;
}
ts = tech_pvt->timestamp_dtmf += samples;
tech_pvt->out_digit_packet[2] = (unsigned char) (duration >> 8);
tech_pvt->out_digit_packet[3] = (unsigned char) duration;
for (x = 0; x < loops; x++) {
frame->flags = 0;
switch_rtp_write_manual(tech_pvt->rtp_session,
tech_pvt->out_digit_packet, 4, 0, 101, ts,
loops == 1 ? tech_pvt->out_digit_seq++ : tech_pvt->out_digit_seq, &frame->flags);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send %s packet for [%c] ts=%d sofar=%u dur=%d\n",
loops == 1 ? "middle" : "end",
tech_pvt->out_digit,
ts,
tech_pvt->out_digit_sofar,
duration);
}
}
if (!tech_pvt->out_digit_dur && tech_pvt->dtmf_queue && switch_queue_size(tech_pvt->dtmf_queue)) {
void *pop;
if (switch_queue_trypop(tech_pvt->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
int x, ts;
struct rfc2833_digit *rdigit = pop;
memset(tech_pvt->out_digit_packet, 0, 4);
tech_pvt->out_digit_sofar = 0;
tech_pvt->out_digit_dur = rdigit->duration;
tech_pvt->out_digit = rdigit->digit;
tech_pvt->out_digit_packet[0] = (unsigned char)switch_char_to_rfc2833(rdigit->digit);
tech_pvt->out_digit_packet[1] = 7;
ts = tech_pvt->timestamp_dtmf += samples;
tech_pvt->out_digit_seq++;
for (x = 0; x < 3; x++) {
frame->flags = 0;
switch_rtp_write_manual(tech_pvt->rtp_session, tech_pvt->out_digit_packet, 4, 1, 101, ts, tech_pvt->out_digit_seq, &frame->flags);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send start packet for [%c] ts=%d sofar=%u dur=%d\n", tech_pvt->out_digit, ts,
tech_pvt->out_digit_sofar, 0);
}
free(rdigit);
}
}
//printf("%s %s->%s send %d bytes %d samples in %d frames ts=%d\n", switch_channel_get_name(channel), tech_pvt->local_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip, frame->datalen, samples, frames, tech_pvt->timestamp_send);
@ -869,29 +771,14 @@ static switch_status_t exosip_waitfor_write(switch_core_session_t *session, int
static switch_status_t exosip_send_dtmf(switch_core_session_t *session, char *digits)
{
struct private_object *tech_pvt;
char *c;
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
if (!tech_pvt->dtmf_queue) {
switch_queue_create(&tech_pvt->dtmf_queue, 100, switch_core_session_get_pool(session));
}
for(c = digits; *c; c++) {
struct rfc2833_digit *rdigit;
if ((rdigit = malloc(sizeof(*rdigit))) != 0) {
memset(rdigit, 0, sizeof(*rdigit));
rdigit->digit = *c;
rdigit->duration = globals.dtmf_duration * (tech_pvt->read_codec.implementation->samples_per_second / 1000);
switch_queue_push(tech_pvt->dtmf_queue, rdigit);
} else {
return SWITCH_STATUS_MEMERR;
}
}
return SWITCH_STATUS_SUCCESS;
return switch_rtp_queue_rfc2833(tech_pvt->rtp_session,
digits,
globals.dtmf_duration * (tech_pvt->read_codec.implementation->samples_per_second / 1000));
}
static switch_status_t exosip_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)

View File

@ -238,7 +238,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *chan
p = dtmf;
while(wr < len && p) {
if (*p > 47 && *p < 58) {
if (is_dtmf(*p)) {
wr++;
} else {
break;
@ -265,7 +265,7 @@ SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf(switch_channel_t *chan
}
switch_mutex_unlock(channel->dtmf_mutex);
if (bytes && switch_event_create(&event, SWITCH_EVENT_CHANNEL_ANSWER) == SWITCH_STATUS_SUCCESS) {
if (bytes && switch_event_create(&event, SWITCH_EVENT_DTMF) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-String", dtmf);
switch_event_fire(&event);

View File

@ -111,6 +111,7 @@ static char *EVENT_NAMES[] = {
"NOTALK",
"SESSION_CRASH",
"MODULE_LOAD",
"DTMF",
"ALL"
};

View File

@ -58,6 +58,11 @@ typedef struct {
} rtp_msg_t;
struct rfc2833_digit {
char digit;
int duration;
};
struct switch_rtp_vad_data {
switch_core_session_t *session;
switch_codec_t vad_codec;
@ -80,6 +85,22 @@ struct switch_rtp_vad_data {
time_t next_scan;
};
struct switch_rtp_rfc2833_data {
switch_queue_t *dtmf_queue;
char out_digit;
unsigned char out_digit_packet[4];
unsigned int out_digit_sofar;
unsigned int out_digit_dur;
uint16_t out_digit_seq;
int32_t timestamp_dtmf;
char last_digit;
unsigned int dc;
time_t last_digit_time;
switch_buffer_t *dtmf_buffer;
switch_mutex_t *dtmf_mutex;
};
struct switch_rtp {
switch_socket_t *sock;
@ -113,6 +134,7 @@ struct switch_rtp {
uint8_t stuncount;
switch_buffer_t *packet_buffer;
struct switch_rtp_vad_data vad_data;
struct switch_rtp_rfc2833_data dtmf_data;
};
static int global_init = 0;
@ -298,7 +320,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
rtp_session->pool = pool;
rtp_session->flags = flags;
switch_mutex_init(&rtp_session->dtmf_data.dtmf_mutex, SWITCH_MUTEX_NESTED, rtp_session->pool);
switch_buffer_create(rtp_session->pool, &rtp_session->dtmf_data.dtmf_buffer, 128);
/* for from address on recvfrom calls */
switch_sockaddr_info_get(&rtp_session->from_addr, NULL, SWITCH_UNSPEC, 0, 0, rtp_session->pool);
@ -514,6 +537,82 @@ SWITCH_DECLARE(void) switch_rtp_clear_flag(switch_rtp_t *rtp_session, switch_rtp
}
static void do_2833(switch_rtp_t *rtp_session)
{
switch_frame_flag_t flags = 0;
uint32_t samples = rtp_session->packet_size;
if (rtp_session->dtmf_data.out_digit_dur > 0) {
int x, ts, loops = 1, duration;
rtp_session->dtmf_data.out_digit_sofar += samples;
if (rtp_session->dtmf_data.out_digit_sofar >= rtp_session->dtmf_data.out_digit_dur) {
duration = rtp_session->dtmf_data.out_digit_dur;
rtp_session->dtmf_data.out_digit_packet[1] |= 0x80;
rtp_session->dtmf_data.out_digit_dur = 0;
loops = 3;
} else {
duration = rtp_session->dtmf_data.out_digit_sofar;
}
ts = rtp_session->dtmf_data.timestamp_dtmf += samples;
rtp_session->dtmf_data.out_digit_packet[2] = (unsigned char) (duration >> 8);
rtp_session->dtmf_data.out_digit_packet[3] = (unsigned char) duration;
for (x = 0; x < loops; x++) {
switch_rtp_write_manual(rtp_session,
rtp_session->dtmf_data.out_digit_packet, 4, 0, 101, ts,
loops == 1 ? rtp_session->dtmf_data.out_digit_seq++ : rtp_session->dtmf_data.out_digit_seq, &flags);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send %s packet for [%c] ts=%d sofar=%u dur=%d\n",
loops == 1 ? "middle" : "end",
rtp_session->dtmf_data.out_digit,
ts,
rtp_session->dtmf_data.out_digit_sofar,
duration);
}
}
if (!rtp_session->dtmf_data.out_digit_dur && rtp_session->dtmf_data.dtmf_queue && switch_queue_size(rtp_session->dtmf_data.dtmf_queue)) {
void *pop;
if (switch_queue_trypop(rtp_session->dtmf_data.dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
int x, ts;
struct rfc2833_digit *rdigit = pop;
memset(rtp_session->dtmf_data.out_digit_packet, 0, 4);
rtp_session->dtmf_data.out_digit_sofar = 0;
rtp_session->dtmf_data.out_digit_dur = rdigit->duration;
rtp_session->dtmf_data.out_digit = rdigit->digit;
rtp_session->dtmf_data.out_digit_packet[0] = (unsigned char)switch_char_to_rfc2833(rdigit->digit);
rtp_session->dtmf_data.out_digit_packet[1] = 7;
ts = rtp_session->dtmf_data.timestamp_dtmf += samples;
rtp_session->dtmf_data.out_digit_seq++;
for (x = 0; x < 3; x++) {
switch_rtp_write_manual(rtp_session,
rtp_session->dtmf_data.out_digit_packet,
4,
1,
101,
ts,
rtp_session->dtmf_data.out_digit_seq,
&flags);
switch_log_printf(SWITCH_CHANNEL_LOG,
SWITCH_LOG_DEBUG,
"Send start packet for [%c] ts=%d sofar=%u dur=%d\n",
rtp_session->dtmf_data.out_digit,
ts,
rtp_session->dtmf_data.out_digit_sofar,
0);
}
free(rdigit);
}
}
}
static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_type, switch_frame_flag_t *flags)
{
switch_size_t bytes;
@ -562,6 +661,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
rtp_session->next_read += rtp_session->ms_per_packet;
}
*payload_type = SWITCH_RTP_CNG_PAYLOAD;
do_2833(rtp_session);
return SWITCH_RTP_CNG_PAYLOAD;
}
@ -610,13 +710,138 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
rtp_session->next_read += rtp_session->ms_per_packet;
*payload_type = rtp_session->recv_msg.header.pt;
/* RFC2833 ... TBD try harder to honor the duration etc.*/
if (*payload_type == 101) {
unsigned char *packet = rtp_session->recv_msg.body;
int end = packet[1]&0x80;
int duration = (packet[2]<<8) + packet[3];
char key = switch_rfc2833_to_char(packet[0]);
/* SHEESH.... Curse you RFC2833 inventors!!!!*/
if ((time(NULL) - rtp_session->dtmf_data.last_digit_time) > 2) {
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.dc = 0;
}
if (duration && end) {
if (key != rtp_session->dtmf_data.last_digit) {
char digit_str[] = {key, 0};
time(&rtp_session->dtmf_data.last_digit_time);
switch_rtp_queue_dtmf(rtp_session, digit_str);
}
if (++rtp_session->dtmf_data.dc >= 3) {
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.dc = 0;
}
rtp_session->dtmf_data.last_digit = key;
} else {
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.dc = 0;
}
}
if (*payload_type == SWITCH_RTP_CNG_PAYLOAD) {
*flags |= SFF_CNG;
}
if (bytes > 0) {
do_2833(rtp_session);
}
return (int) bytes;
}
SWITCH_DECLARE(switch_size_t) switch_rtp_has_dtmf(switch_rtp_t *rtp_session)
{
switch_size_t has;
assert(rtp_session != NULL);
switch_mutex_lock(rtp_session->dtmf_data.dtmf_mutex);
has = switch_buffer_inuse(rtp_session->dtmf_data.dtmf_buffer);
switch_mutex_unlock(rtp_session->dtmf_data.dtmf_mutex);
return has;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_dtmf(switch_rtp_t *rtp_session, char *dtmf)
{
switch_status_t status;
register switch_size_t len, inuse;
switch_size_t wr = 0;
char *p;
assert(rtp_session != NULL);
switch_mutex_lock(rtp_session->dtmf_data.dtmf_mutex);
inuse = switch_buffer_inuse(rtp_session->dtmf_data.dtmf_buffer);
len = strlen(dtmf);
if (len + inuse > switch_buffer_len(rtp_session->dtmf_data.dtmf_buffer)) {
switch_buffer_toss(rtp_session->dtmf_data.dtmf_buffer, strlen(dtmf));
}
p = dtmf;
while(wr < len && p) {
if (is_dtmf(*p)) {
wr++;
} else {
break;
}
p++;
}
status = switch_buffer_write(rtp_session->dtmf_data.dtmf_buffer, dtmf, wr) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_MEMERR;
switch_mutex_unlock(rtp_session->dtmf_data.dtmf_mutex);
return status;
}
SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, char *dtmf, switch_size_t len)
{
switch_size_t bytes;
assert(rtp_session != NULL);
switch_mutex_lock(rtp_session->dtmf_data.dtmf_mutex);
if ((bytes = switch_buffer_read(rtp_session->dtmf_data.dtmf_buffer, dtmf, len)) > 0) {
*(dtmf + bytes) = '\0';
}
switch_mutex_unlock(rtp_session->dtmf_data.dtmf_mutex);
return bytes;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_session, char *digits, uint32_t duration)
{
char *c;
if (!rtp_session->dtmf_data.dtmf_queue) {
switch_queue_create(&rtp_session->dtmf_data.dtmf_queue, 100, rtp_session->pool);
}
for(c = digits; *c; c++) {
struct rfc2833_digit *rdigit;
if ((rdigit = malloc(sizeof(*rdigit))) != 0) {
memset(rdigit, 0, sizeof(*rdigit));
rdigit->digit = *c;
rdigit->duration = duration;
switch_queue_push(rtp_session->dtmf_data.dtmf_queue, rdigit);
} else {
return SWITCH_STATUS_MEMERR;
}
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_read(switch_rtp_t *rtp_session, void *data, uint32_t *datalen, switch_payload_t *payload_type, switch_frame_flag_t *flags)
{
@ -664,7 +889,11 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp
}
SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read(switch_rtp_t *rtp_session, void **data, uint32_t *datalen, switch_payload_t *payload_type, switch_frame_flag_t *flags)
SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read(switch_rtp_t *rtp_session,
void **data,
uint32_t *datalen,
switch_payload_t *payload_type,
switch_frame_flag_t *flags)
{
int bytes = rtp_common_read(rtp_session, payload_type, flags);