mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-15 08:29:45 +00:00
move CNG into the core and rearrange a few things
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@1066 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
a55bb56ff2
commit
0af60e1b2f
@ -214,7 +214,6 @@ codec_prefs => PCMU
|
|||||||
password => mypass
|
password => mypass
|
||||||
dialplan => demo
|
dialplan => demo
|
||||||
message => Jingle all the way
|
message => Jingle all the way
|
||||||
generate_silence => yes
|
|
||||||
ip => 0.0.0.0
|
ip => 0.0.0.0
|
||||||
; or ;
|
; or ;
|
||||||
;ip => my_lan_ip
|
;ip => my_lan_ip
|
||||||
|
@ -56,8 +56,8 @@ struct switch_frame {
|
|||||||
switch_size_t samples;
|
switch_size_t samples;
|
||||||
/*! the rate of the frame */
|
/*! the rate of the frame */
|
||||||
int rate;
|
int rate;
|
||||||
/*! the timestamp of the frame */
|
/*! frame flags */
|
||||||
int32_t timestamp;
|
switch_frame_flag flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -45,6 +45,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SWITCH_RTP_MAX_BUF_LEN 16384
|
||||||
|
|
||||||
///\defgroup rtp RTP (RealTime Transport Protocol)
|
///\defgroup rtp RTP (RealTime Transport Protocol)
|
||||||
///\ingroup core1
|
///\ingroup core1
|
||||||
@ -134,9 +135,10 @@ SWITCH_DECLARE(void) switch_rtp_set_invald_handler(switch_rtp *rtp_session, swit
|
|||||||
\param data the data to read
|
\param data the data to read
|
||||||
\param datalen the length of the data
|
\param datalen the length of the data
|
||||||
\param payload_type the IANA payload of the packet
|
\param payload_type the IANA payload of the packet
|
||||||
|
\param flags flags
|
||||||
\return the number of bytes read
|
\return the number of bytes read
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(int) switch_rtp_read(switch_rtp *rtp_session, void *data, uint32_t datalen, int *payload_type);
|
SWITCH_DECLARE(int) switch_rtp_read(switch_rtp *rtp_session, void *data, uint32_t datalen, int *payload_type, switch_frame_flag *flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Read data from a given RTP session without copying
|
\brief Read data from a given RTP session without copying
|
||||||
@ -145,7 +147,7 @@ SWITCH_DECLARE(int) switch_rtp_read(switch_rtp *rtp_session, void *data, uint32_
|
|||||||
\param payload_type the IANA payload of the packet
|
\param payload_type the IANA payload of the packet
|
||||||
\return the number of bytes read
|
\return the number of bytes read
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(int) switch_rtp_zerocopy_read(switch_rtp *rtp_session, void **data, int *payload_type);
|
SWITCH_DECLARE(int) switch_rtp_zerocopy_read(switch_rtp *rtp_session, void **data, int *payload_type, switch_frame_flag *flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Write data to a given RTP session
|
\brief Write data to a given RTP session
|
||||||
@ -153,6 +155,7 @@ SWITCH_DECLARE(int) switch_rtp_zerocopy_read(switch_rtp *rtp_session, void **dat
|
|||||||
\param data data to write
|
\param data data to write
|
||||||
\param datalen the size of the data
|
\param datalen the size of the data
|
||||||
\param ts then number of bytes to increment the timestamp by
|
\param ts then number of bytes to increment the timestamp by
|
||||||
|
\param flags flags
|
||||||
\return the number of bytes written
|
\return the number of bytes written
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(int) switch_rtp_write(switch_rtp *rtp_session, void *data, int datalen, uint32_t ts);
|
SWITCH_DECLARE(int) switch_rtp_write(switch_rtp *rtp_session, void *data, int datalen, uint32_t ts);
|
||||||
|
@ -250,27 +250,38 @@ typedef enum {
|
|||||||
\brief Channel Flags
|
\brief Channel Flags
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
CF_SEND_AUDIO = (1 << 0) - Channel will send audio
|
CF_ANSWERED = (1 << 0) - Channel is answered
|
||||||
CF_RECV_AUDIO = (1 << 1) - Channel will receive audio
|
CF_OUTBOUND = (1 << 1) - Channel is an outbound channel
|
||||||
CF_ANSWERED = (1 << 2) - Channel is answered
|
CF_EARLY_MEDIA = (1 << 2) - Channel is ready for audio before answer
|
||||||
CF_OUTBOUND = (1 << 3) - Channel is an outbound channel
|
CF_ORIGINATOR = (1 << 3) - Channel is an originator
|
||||||
CF_EARLY_MEDIA = (1 << 4) - Channel is ready for audio before answer
|
CF_TRANSFER = (1 << 4) - Channel is being transfered
|
||||||
CF_ORIGINATOR = (1 << 5) - Channel is an originator
|
CF_ACCEPT_CNG = (1 << 5) - Channel will accept CNG frames
|
||||||
CF_TRANSFER = (1 << 6) - Channel is being transfered
|
|
||||||
</pre>
|
</pre>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CF_SEND_AUDIO = (1 << 0),
|
CF_ANSWERED = (1 << 0),
|
||||||
CF_RECV_AUDIO = (1 << 1),
|
CF_OUTBOUND = (1 << 1),
|
||||||
CF_ANSWERED = (1 << 2),
|
CF_EARLY_MEDIA = (1 << 2),
|
||||||
CF_OUTBOUND = (1 << 3),
|
CF_ORIGINATOR = (1 << 3),
|
||||||
CF_EARLY_MEDIA = (1 << 4),
|
CF_TRANSFER = (1 << 4),
|
||||||
CF_ORIGINATOR = (1 << 5),
|
CF_ACCEPT_CNG = (1 << 5)
|
||||||
CF_TRANSFER = (1 << 6)
|
|
||||||
} switch_channel_flag;
|
} switch_channel_flag;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\enum switch_frame_flag
|
||||||
|
\brief Frame Flags
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
CF_CNG = (1 << 0) - Frame represents comfort noise
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
SFF_CNG = (1 << 0)
|
||||||
|
} switch_frame_flag;
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\enum switch_signal
|
\enum switch_signal
|
||||||
\brief Signals to send to channels
|
\brief Signals to send to channels
|
||||||
|
@ -46,13 +46,8 @@ typedef enum {
|
|||||||
TFLAG_VOICE = (1 << 6),
|
TFLAG_VOICE = (1 << 6),
|
||||||
TFLAG_RTP_READY = (1 << 7),
|
TFLAG_RTP_READY = (1 << 7),
|
||||||
TFLAG_CODEC_READY = (1 << 8),
|
TFLAG_CODEC_READY = (1 << 8),
|
||||||
TFLAG_SILENCE = (1 << 9)
|
|
||||||
} TFLAGS;
|
} TFLAGS;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PFLAG_GENSILENCE = (1 << 0)
|
|
||||||
} PFLAGS;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GFLAG_MY_CODEC_PREFS = (1 << 0)
|
GFLAG_MY_CODEC_PREFS = (1 << 0)
|
||||||
} GFLAGS;
|
} GFLAGS;
|
||||||
@ -92,10 +87,7 @@ struct private_object {
|
|||||||
switch_codec read_codec;
|
switch_codec read_codec;
|
||||||
switch_codec write_codec;
|
switch_codec write_codec;
|
||||||
struct switch_frame read_frame;
|
struct switch_frame read_frame;
|
||||||
struct switch_frame cng_frame;
|
|
||||||
struct mdl_profile *profile;
|
struct mdl_profile *profile;
|
||||||
unsigned char read_buf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
|
|
||||||
unsigned char cng_buf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
|
|
||||||
switch_core_session *session;
|
switch_core_session *session;
|
||||||
switch_caller_profile *caller_profile;
|
switch_caller_profile *caller_profile;
|
||||||
unsigned short samprate;
|
unsigned short samprate;
|
||||||
@ -126,7 +118,6 @@ struct private_object {
|
|||||||
int32_t timestamp_dtmf;
|
int32_t timestamp_dtmf;
|
||||||
char *codec_name;
|
char *codec_name;
|
||||||
int codec_num;
|
int codec_num;
|
||||||
switch_time_t cng_next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rfc2833_digit {
|
struct rfc2833_digit {
|
||||||
@ -317,13 +308,7 @@ static void *SWITCH_THREAD_FUNC negotiate_thread_run(switch_thread *thread, void
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tech_pvt->read_frame.data = tech_pvt->read_buf;
|
|
||||||
tech_pvt->read_frame.buflen = sizeof(tech_pvt->read_buf);
|
|
||||||
|
|
||||||
tech_pvt->cng_frame.data = tech_pvt->cng_buf;
|
|
||||||
tech_pvt->cng_frame.buflen = sizeof(tech_pvt->cng_buf);
|
|
||||||
|
|
||||||
|
|
||||||
if (switch_core_codec_init(&tech_pvt->read_codec,
|
if (switch_core_codec_init(&tech_pvt->read_codec,
|
||||||
tech_pvt->codec_name,
|
tech_pvt->codec_name,
|
||||||
8000,
|
8000,
|
||||||
@ -337,9 +322,6 @@ static void *SWITCH_THREAD_FUNC negotiate_thread_run(switch_thread *thread, void
|
|||||||
}
|
}
|
||||||
tech_pvt->read_frame.rate = tech_pvt->read_codec.implementation->samples_per_second;
|
tech_pvt->read_frame.rate = tech_pvt->read_codec.implementation->samples_per_second;
|
||||||
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
|
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
|
||||||
tech_pvt->cng_frame.rate = tech_pvt->read_codec.implementation->samples_per_second;
|
|
||||||
tech_pvt->cng_frame.codec = &tech_pvt->read_codec;
|
|
||||||
memset(tech_pvt->cng_buf,255, sizeof(tech_pvt->cng_buf));
|
|
||||||
|
|
||||||
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Set Read Codec to %s\n", tech_pvt->codec_name);
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Set Read Codec to %s\n", tech_pvt->codec_name);
|
||||||
|
|
||||||
@ -358,7 +340,6 @@ static void *SWITCH_THREAD_FUNC negotiate_thread_run(switch_thread *thread, void
|
|||||||
|
|
||||||
switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
|
switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
|
||||||
switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
|
switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
|
||||||
//switch_set_flag(tech_pvt, TFLAG_SILENCE);
|
|
||||||
|
|
||||||
//printf("WAIT %s %d\n", switch_channel_get_name(channel), switch_test_flag(tech_pvt, TFLAG_OUTBOUND));
|
//printf("WAIT %s %d\n", switch_channel_get_name(channel), switch_test_flag(tech_pvt, TFLAG_OUTBOUND));
|
||||||
|
|
||||||
@ -402,6 +383,8 @@ static switch_status channel_on_init(switch_core_session *session)
|
|||||||
channel = switch_core_session_get_channel(session);
|
channel = switch_core_session_get_channel(session);
|
||||||
assert(channel != NULL);
|
assert(channel != NULL);
|
||||||
|
|
||||||
|
tech_pvt->read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN;
|
||||||
|
|
||||||
/* Move Channel's State Machine to RING */
|
/* Move Channel's State Machine to RING */
|
||||||
switch_channel_set_state(channel, CS_RING);
|
switch_channel_set_state(channel, CS_RING);
|
||||||
|
|
||||||
@ -557,7 +540,6 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
|
|||||||
size_t bytes = 0, samples = 0, frames = 0, ms = 0;
|
size_t bytes = 0, samples = 0, frames = 0, ms = 0;
|
||||||
switch_channel *channel = NULL;
|
switch_channel *channel = NULL;
|
||||||
int payload = 0;
|
int payload = 0;
|
||||||
switch_time_t now;
|
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(session);
|
channel = switch_core_session_get_channel(session);
|
||||||
assert(channel != NULL);
|
assert(channel != NULL);
|
||||||
@ -578,28 +560,12 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
|
|||||||
assert(tech_pvt->rtp_session != NULL);
|
assert(tech_pvt->rtp_session != NULL);
|
||||||
tech_pvt->read_frame.datalen = 0;
|
tech_pvt->read_frame.datalen = 0;
|
||||||
|
|
||||||
|
|
||||||
while (!switch_test_flag(tech_pvt, TFLAG_BYE) && switch_test_flag(tech_pvt, TFLAG_IO) && tech_pvt->read_frame.datalen == 0) {
|
while (!switch_test_flag(tech_pvt, TFLAG_BYE) && switch_test_flag(tech_pvt, TFLAG_IO) && tech_pvt->read_frame.datalen == 0) {
|
||||||
payload = -1;
|
payload = -1;
|
||||||
tech_pvt->read_frame.datalen = switch_rtp_read(tech_pvt->rtp_session, tech_pvt->read_frame.data, sizeof(tech_pvt->read_buf), &payload);
|
tech_pvt->read_frame.flags = 0;
|
||||||
if (switch_test_flag(tech_pvt, TFLAG_SILENCE)) {
|
tech_pvt->read_frame.datalen = switch_rtp_zerocopy_read(tech_pvt->rtp_session, &tech_pvt->read_frame.data, &payload, &tech_pvt->read_frame.flags);
|
||||||
if (tech_pvt->read_frame.datalen) {
|
|
||||||
switch_clear_flag(tech_pvt, TFLAG_SILENCE);
|
|
||||||
} else {
|
|
||||||
now = switch_time_now();
|
|
||||||
if (now >= tech_pvt->cng_next) {
|
|
||||||
tech_pvt->cng_next += ms;
|
|
||||||
if (!tech_pvt->cng_frame.datalen) {
|
|
||||||
tech_pvt->cng_frame.datalen = bytes;
|
|
||||||
}
|
|
||||||
memset(tech_pvt->cng_frame.data, 255, tech_pvt->cng_frame.datalen);
|
|
||||||
//printf("GENERATE X bytes=%d payload=%d frames=%d samples=%d ms=%d ts=%d sampcount=%d\n", tech_pvt->cng_frame.datalen, payload, frames, samples, ms, tech_pvt->timestamp_recv, tech_pvt->read_frame.samples);
|
|
||||||
*frame = &tech_pvt->cng_frame;
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
switch_yield(1000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RFC2833 ... TBD try harder to honor the duration etc.*/
|
/* RFC2833 ... TBD try harder to honor the duration etc.*/
|
||||||
if (payload == 101) {
|
if (payload == 101) {
|
||||||
@ -629,23 +595,6 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (switch_test_flag(tech_pvt->profile, PFLAG_GENSILENCE)) {
|
|
||||||
if ((switch_test_flag(tech_pvt, TFLAG_SILENCE) || payload == 13) && tech_pvt->cng_frame.datalen) {
|
|
||||||
memset(tech_pvt->cng_frame.data, 255, tech_pvt->cng_frame.datalen);
|
|
||||||
*frame = &tech_pvt->cng_frame;
|
|
||||||
//printf("GENERATE bytes=%d payload=%d frames=%d samples=%d ms=%d ts=%d sampcount=%d\n", tech_pvt->cng_frame.datalen, payload, frames, samples, ms, tech_pvt->timestamp_recv, tech_pvt->read_frame.samples);
|
|
||||||
switch_set_flag(tech_pvt, TFLAG_SILENCE);
|
|
||||||
tech_pvt->cng_next = switch_time_now() + ms;
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (payload != tech_pvt->codec_num) {
|
|
||||||
switch_yield(1000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tech_pvt->read_frame.datalen > 0) {
|
if (tech_pvt->read_frame.datalen > 0) {
|
||||||
bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
|
bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
|
||||||
frames = (tech_pvt->read_frame.datalen / bytes);
|
frames = (tech_pvt->read_frame.datalen / bytes);
|
||||||
@ -653,14 +602,8 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
|
|||||||
ms = frames * tech_pvt->read_codec.implementation->microseconds_per_frame;
|
ms = frames * tech_pvt->read_codec.implementation->microseconds_per_frame;
|
||||||
tech_pvt->timestamp_recv += (int32_t) samples;
|
tech_pvt->timestamp_recv += (int32_t) samples;
|
||||||
tech_pvt->read_frame.samples = (int) samples;
|
tech_pvt->read_frame.samples = (int) samples;
|
||||||
if (switch_test_flag(tech_pvt->profile, PFLAG_GENSILENCE)) {
|
|
||||||
//memcpy(tech_pvt->cng_buf, tech_pvt->read_buf, tech_pvt->read_frame.datalen);
|
|
||||||
tech_pvt->cng_frame.datalen = tech_pvt->read_frame.datalen;
|
|
||||||
tech_pvt->cng_frame.samples = tech_pvt->read_frame.samples;
|
|
||||||
switch_clear_flag(tech_pvt, TFLAG_SILENCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("READ bytes=%d payload=%d frames=%d samples=%d ms=%d ts=%d sampcount=%d\n", tech_pvt->read_frame.datalen, payload, frames, samples, ms, tech_pvt->timestamp_recv, tech_pvt->read_frame.samples);
|
//printf("READ bytes=%d payload=%d frames=%d samples=%d ms=%d ts=%d sampcount=%d\n", (int)tech_pvt->read_frame.datalen, (int)payload, (int)frames, (int)samples, (int)ms, (int)tech_pvt->timestamp_recv, (int)tech_pvt->read_frame.samples);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1072,10 +1015,6 @@ static switch_status load_config(void)
|
|||||||
profile->name = switch_core_strdup(module_pool, val);
|
profile->name = switch_core_strdup(module_pool, val);
|
||||||
} else if (!strcmp(var, "message")) {
|
} else if (!strcmp(var, "message")) {
|
||||||
profile->message = switch_core_strdup(module_pool, val);
|
profile->message = switch_core_strdup(module_pool, val);
|
||||||
} else if (!strcmp(var, "generate_silence")) {
|
|
||||||
if (switch_true(val)) {
|
|
||||||
switch_set_flag(profile, PFLAG_GENSILENCE);
|
|
||||||
}
|
|
||||||
} else if (!strcmp(var, "ip")) {
|
} else if (!strcmp(var, "ip")) {
|
||||||
profile->ip = switch_core_strdup(module_pool, val);
|
profile->ip = switch_core_strdup(module_pool, val);
|
||||||
} else if (!strcmp(var, "extip")) {
|
} else if (!strcmp(var, "extip")) {
|
||||||
@ -1331,7 +1270,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
|
|||||||
tech_pvt->remote_ip,
|
tech_pvt->remote_ip,
|
||||||
tech_pvt->remote_port,
|
tech_pvt->remote_port,
|
||||||
tech_pvt->codec_num,
|
tech_pvt->codec_num,
|
||||||
switch_test_flag(tech_pvt->profile, PFLAG_GENSILENCE) ? SWITCH_RTP_NOBLOCK : 0,
|
0,
|
||||||
&err, switch_core_session_get_pool(tech_pvt->session)))) {
|
&err, switch_core_session_get_pool(tech_pvt->session)))) {
|
||||||
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "RTP ERROR %s\n", err);
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "RTP ERROR %s\n", err);
|
||||||
switch_channel_hangup(channel);
|
switch_channel_hangup(channel);
|
||||||
|
@ -66,8 +66,7 @@ typedef enum {
|
|||||||
TFLAG_RTP = (1 << 7),
|
TFLAG_RTP = (1 << 7),
|
||||||
TFLAG_BYE = (1 << 8),
|
TFLAG_BYE = (1 << 8),
|
||||||
TFLAG_ANS = (1 << 9),
|
TFLAG_ANS = (1 << 9),
|
||||||
TFLAG_EARLY_MEDIA = (1 << 10),
|
TFLAG_EARLY_MEDIA = (1 << 10)
|
||||||
TFLAG_SILENCE = (1 << 11)
|
|
||||||
|
|
||||||
} TFLAGS;
|
} TFLAGS;
|
||||||
|
|
||||||
@ -95,10 +94,8 @@ struct private_object {
|
|||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
switch_core_session *session;
|
switch_core_session *session;
|
||||||
switch_frame read_frame;
|
switch_frame read_frame;
|
||||||
switch_frame cng_frame;
|
|
||||||
switch_codec read_codec;
|
switch_codec read_codec;
|
||||||
switch_codec write_codec;
|
switch_codec write_codec;
|
||||||
unsigned char cng_buf[320];
|
|
||||||
switch_caller_profile *caller_profile;
|
switch_caller_profile *caller_profile;
|
||||||
int cid;
|
int cid;
|
||||||
int did;
|
int did;
|
||||||
@ -123,7 +120,6 @@ struct private_object {
|
|||||||
switch_mutex_t *rtp_lock;
|
switch_mutex_t *rtp_lock;
|
||||||
switch_queue_t *dtmf_queue;
|
switch_queue_t *dtmf_queue;
|
||||||
char out_digit;
|
char out_digit;
|
||||||
switch_time_t cng_next;
|
|
||||||
switch_time_t last_read;
|
switch_time_t last_read;
|
||||||
unsigned char out_digit_packet[4];
|
unsigned char out_digit_packet[4];
|
||||||
unsigned int out_digit_sofar;
|
unsigned int out_digit_sofar;
|
||||||
@ -232,11 +228,7 @@ static switch_status exosip_on_init(switch_core_session *session)
|
|||||||
tech_pvt = switch_core_session_get_private(session);
|
tech_pvt = switch_core_session_get_private(session);
|
||||||
assert(tech_pvt != NULL);
|
assert(tech_pvt != NULL);
|
||||||
|
|
||||||
tech_pvt->read_frame.data = tech_pvt->cng_buf;
|
tech_pvt->read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN;
|
||||||
tech_pvt->read_frame.buflen = sizeof(tech_pvt->cng_buf);
|
|
||||||
|
|
||||||
tech_pvt->cng_frame.data = tech_pvt->cng_buf;
|
|
||||||
tech_pvt->cng_frame.buflen = sizeof(tech_pvt->cng_buf);
|
|
||||||
|
|
||||||
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "EXOSIP INIT\n");
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "EXOSIP INIT\n");
|
||||||
|
|
||||||
@ -582,27 +574,8 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
|
|||||||
while (!switch_test_flag(tech_pvt, TFLAG_BYE) && switch_test_flag(tech_pvt, TFLAG_IO)
|
while (!switch_test_flag(tech_pvt, TFLAG_BYE) && switch_test_flag(tech_pvt, TFLAG_IO)
|
||||||
&& tech_pvt->read_frame.datalen == 0) {
|
&& tech_pvt->read_frame.datalen == 0) {
|
||||||
now = switch_time_now();
|
now = switch_time_now();
|
||||||
tech_pvt->read_frame.datalen = switch_rtp_zerocopy_read(tech_pvt->rtp_session, &tech_pvt->read_frame.data, &payload);
|
tech_pvt->read_frame.flags = 0;
|
||||||
|
tech_pvt->read_frame.datalen = switch_rtp_zerocopy_read(tech_pvt->rtp_session, &tech_pvt->read_frame.data, &payload, &tech_pvt->read_frame.flags);
|
||||||
if (switch_test_flag(tech_pvt, TFLAG_SILENCE)) {
|
|
||||||
if (tech_pvt->read_frame.datalen) {
|
|
||||||
switch_clear_flag(tech_pvt, TFLAG_SILENCE);
|
|
||||||
} else {
|
|
||||||
now = switch_time_now();
|
|
||||||
if (now >= tech_pvt->cng_next) {
|
|
||||||
tech_pvt->cng_next += ms;
|
|
||||||
if (!tech_pvt->cng_frame.datalen) {
|
|
||||||
tech_pvt->cng_frame.datalen = bytes;
|
|
||||||
}
|
|
||||||
memset(tech_pvt->cng_frame.data, 255, tech_pvt->cng_frame.datalen);
|
|
||||||
//printf("GENERATE X bytes=%d payload=%d frames=%d samples=%d ms=%d ts=%d sampcount=%d\n", tech_pvt->cng_frame.datalen, payload, frames, samples, ms, tech_pvt->timestamp_recv, tech_pvt->read_frame.samples);
|
|
||||||
*frame = &tech_pvt->cng_frame;
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
switch_yield(1000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (timeout > -1) {
|
if (timeout > -1) {
|
||||||
@ -640,23 +613,6 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (switch_test_flag(&globals, TFLAG_SILENCE)) {
|
|
||||||
if ((switch_test_flag(tech_pvt, TFLAG_SILENCE) || payload == 13) && tech_pvt->cng_frame.datalen) {
|
|
||||||
*frame = &tech_pvt->cng_frame;
|
|
||||||
//printf("GENERATE bytes=%d payload=%d frames=%d samples=%d ms=%d ts=%d sampcount=%d\n", tech_pvt->cng_frame.datalen, payload, frames, samples, ms, tech_pvt->timestamp_recv, tech_pvt->read_frame.samples);
|
|
||||||
switch_set_flag(tech_pvt, TFLAG_SILENCE);
|
|
||||||
tech_pvt->cng_next = switch_time_now() + ms;
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (payload != tech_pvt->payload_num) {
|
|
||||||
tech_pvt->read_frame.datalen = 0;
|
|
||||||
switch_yield(1000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tech_pvt->read_frame.datalen > 0) {
|
if (tech_pvt->read_frame.datalen > 0) {
|
||||||
tech_pvt->last_read = switch_time_now();
|
tech_pvt->last_read = switch_time_now();
|
||||||
bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
|
bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
|
||||||
@ -665,21 +621,12 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
|
|||||||
ms = frames * tech_pvt->read_codec.implementation->microseconds_per_frame;
|
ms = frames * tech_pvt->read_codec.implementation->microseconds_per_frame;
|
||||||
tech_pvt->timestamp_recv += (int32_t) samples;
|
tech_pvt->timestamp_recv += (int32_t) samples;
|
||||||
tech_pvt->read_frame.samples = (int) samples;
|
tech_pvt->read_frame.samples = (int) samples;
|
||||||
if (switch_test_flag(&globals, TFLAG_SILENCE)) {
|
|
||||||
tech_pvt->cng_frame.datalen = tech_pvt->read_frame.datalen;
|
|
||||||
tech_pvt->cng_frame.samples = tech_pvt->read_frame.samples;
|
|
||||||
switch_clear_flag(tech_pvt, TFLAG_SILENCE);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_yield(1000);
|
switch_yield(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
memset(tech_pvt->cng_buf, 0, 160);
|
|
||||||
tech_pvt->read_frame.data = tech_pvt->cng_buf;
|
|
||||||
tech_pvt->read_frame.datalen = 160;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_clear_flag(tech_pvt, TFLAG_READING);
|
switch_clear_flag(tech_pvt, TFLAG_READING);
|
||||||
@ -1263,9 +1210,6 @@ static switch_status exosip_create_call(eXosip_event_t * event)
|
|||||||
ms = tech_pvt->write_codec.implementation->microseconds_per_frame / 1000;
|
ms = tech_pvt->write_codec.implementation->microseconds_per_frame / 1000;
|
||||||
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Inbound Codec %s/%d %d ms\n", dname, rate, ms);
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Inbound Codec %s/%d %d ms\n", dname, rate, ms);
|
||||||
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
|
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
|
||||||
tech_pvt->cng_frame.rate = tech_pvt->read_codec.implementation->samples_per_second;
|
|
||||||
tech_pvt->cng_frame.codec = &tech_pvt->read_codec;
|
|
||||||
memset(tech_pvt->cng_buf,255, sizeof(tech_pvt->cng_buf));
|
|
||||||
switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
|
switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
|
||||||
switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
|
switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
|
||||||
}
|
}
|
||||||
@ -1432,9 +1376,6 @@ static void handle_answer(eXosip_event_t * event)
|
|||||||
ms = tech_pvt->write_codec.implementation->microseconds_per_frame / 1000;
|
ms = tech_pvt->write_codec.implementation->microseconds_per_frame / 1000;
|
||||||
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Outbound Codec %s/%d %d ms\n", dname, rate, ms);
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Outbound Codec %s/%d %d ms\n", dname, rate, ms);
|
||||||
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
|
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
|
||||||
tech_pvt->cng_frame.rate = tech_pvt->read_codec.implementation->samples_per_second;
|
|
||||||
tech_pvt->cng_frame.codec = &tech_pvt->read_codec;
|
|
||||||
memset(tech_pvt->cng_buf,255, sizeof(tech_pvt->cng_buf));
|
|
||||||
switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
|
switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
|
||||||
switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
|
switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
|
||||||
}
|
}
|
||||||
@ -1605,10 +1546,6 @@ static int config_exosip(int reload)
|
|||||||
globals.port = atoi(val);
|
globals.port = atoi(val);
|
||||||
} else if (!strcmp(var, "host")) {
|
} else if (!strcmp(var, "host")) {
|
||||||
set_global_host(val);
|
set_global_host(val);
|
||||||
} else if (!strcmp(var, "cng")) {
|
|
||||||
if (switch_true(val)) {
|
|
||||||
switch_set_flag(&globals, TFLAG_SILENCE);
|
|
||||||
}
|
|
||||||
} else if (!strcmp(var, "dialplan")) {
|
} else if (!strcmp(var, "dialplan")) {
|
||||||
set_global_dialplan(val);
|
set_global_dialplan(val);
|
||||||
} else if (!strcmp(var, "codec_prefs")) {
|
} else if (!strcmp(var, "codec_prefs")) {
|
||||||
|
@ -653,6 +653,7 @@ static switch_status channel_write_frame(switch_core_session *session, switch_fr
|
|||||||
switch_swap_linear(frame->data, (int) frame->datalen / 2);
|
switch_swap_linear(frame->data, (int) frame->datalen / 2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
//printf("Send %ld %d\n", time(NULL), (int) frame->datalen);
|
||||||
iax_send_voice(tech_pvt->iax_session, tech_pvt->codec, frame->data, (int) frame->datalen,
|
iax_send_voice(tech_pvt->iax_session, tech_pvt->codec, frame->data, (int) frame->datalen,
|
||||||
tech_pvt->write_codec.implementation->samples_per_frame);
|
tech_pvt->write_codec.implementation->samples_per_frame);
|
||||||
|
|
||||||
|
@ -957,9 +957,11 @@ SWITCH_DECLARE(switch_status) switch_core_session_read_frame(switch_core_session
|
|||||||
assert(session != NULL);
|
assert(session != NULL);
|
||||||
assert(*frame != NULL);
|
assert(*frame != NULL);
|
||||||
|
|
||||||
/* if you think this code is redundant.... too bad! I like to understand what I'm doing */
|
if (switch_test_flag(*frame, SFF_CNG)) {
|
||||||
if ((session->read_codec && (*frame)->codec
|
return SWITCH_STATUS_SUCCESS;
|
||||||
&& session->read_codec->implementation != (*frame)->codec->implementation)) {
|
}
|
||||||
|
|
||||||
|
if ((session->read_codec && (*frame)->codec && session->read_codec->implementation != (*frame)->codec->implementation)) {
|
||||||
need_codec = TRUE;
|
need_codec = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1086,8 +1088,7 @@ SWITCH_DECLARE(switch_status) switch_core_session_read_frame(switch_core_session
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static switch_status perform_write(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags,
|
static switch_status perform_write(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id)
|
||||||
int stream_id)
|
|
||||||
{
|
{
|
||||||
struct switch_io_event_hook_write_frame *ptr;
|
struct switch_io_event_hook_write_frame *ptr;
|
||||||
switch_status status = SWITCH_STATUS_FALSE;
|
switch_status status = SWITCH_STATUS_FALSE;
|
||||||
@ -1119,7 +1120,16 @@ SWITCH_DECLARE(switch_status) switch_core_session_write_frame(switch_core_sessio
|
|||||||
assert(frame != NULL);
|
assert(frame != NULL);
|
||||||
assert(frame->codec != NULL);
|
assert(frame->codec != NULL);
|
||||||
|
|
||||||
/* if you think this code is redundant.... too bad! I like to understand what I'm doing */
|
if (switch_test_flag(frame, SFF_CNG)) {
|
||||||
|
|
||||||
|
if (switch_channel_test_flag(session->channel, CF_ACCEPT_CNG)) {
|
||||||
|
return perform_write(session, frame, timeout, flag, stream_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((session->write_codec && frame->codec && session->write_codec->implementation != frame->codec->implementation)) {
|
if ((session->write_codec && frame->codec && session->write_codec->implementation != frame->codec->implementation)) {
|
||||||
need_codec = TRUE;
|
need_codec = TRUE;
|
||||||
}
|
}
|
||||||
@ -2219,7 +2229,7 @@ SWITCH_DECLARE(switch_core_session *) switch_core_session_request(const switch_e
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_channel_init(session->channel, session, CS_NEW, (CF_SEND_AUDIO | CF_RECV_AUDIO));
|
switch_channel_init(session->channel, session, CS_NEW, 0);
|
||||||
|
|
||||||
/* The session *IS* the pool you may not alter it because you have no idea how
|
/* The session *IS* the pool you may not alter it because you have no idea how
|
||||||
its all private it will be passed to the thread run function */
|
its all private it will be passed to the thread run function */
|
||||||
|
@ -41,9 +41,9 @@
|
|||||||
|
|
||||||
#define MAX_KEY_LEN 64
|
#define MAX_KEY_LEN 64
|
||||||
#define rtp_header_len 12
|
#define rtp_header_len 12
|
||||||
#define RTP_MAX_BUF_LEN 16384
|
|
||||||
#define RTP_START_PORT 16384
|
#define RTP_START_PORT 16384
|
||||||
#define RTP_END_PORT 32768
|
#define RTP_END_PORT 32768
|
||||||
|
#define SWITCH_RTP_CNG_PAYLOAD 13
|
||||||
|
|
||||||
static switch_port_t NEXT_PORT = RTP_START_PORT;
|
static switch_port_t NEXT_PORT = RTP_START_PORT;
|
||||||
static switch_mutex_t *port_lock = NULL;
|
static switch_mutex_t *port_lock = NULL;
|
||||||
@ -51,8 +51,8 @@ static switch_mutex_t *port_lock = NULL;
|
|||||||
typedef srtp_hdr_t rtp_hdr_t;
|
typedef srtp_hdr_t rtp_hdr_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
srtp_hdr_t header;
|
srtp_hdr_t header;
|
||||||
char body[RTP_MAX_BUF_LEN];
|
char body[SWITCH_RTP_MAX_BUF_LEN];
|
||||||
} rtp_msg_t;
|
} rtp_msg_t;
|
||||||
|
|
||||||
struct switch_rtp {
|
struct switch_rtp {
|
||||||
@ -85,6 +85,9 @@ struct switch_rtp {
|
|||||||
|
|
||||||
static int global_init = 0;
|
static int global_init = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static switch_status ice_out(switch_rtp *rtp_session)
|
static switch_status ice_out(switch_rtp *rtp_session)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -332,7 +335,7 @@ SWITCH_DECLARE(void) switch_rtp_set_invald_handler(switch_rtp *rtp_session, swit
|
|||||||
rtp_session->invalid_handler = on_invalid;
|
rtp_session->invalid_handler = on_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(int) switch_rtp_read(switch_rtp *rtp_session, void *data, uint32_t datalen, int *payload_type)
|
SWITCH_DECLARE(int) switch_rtp_read(switch_rtp *rtp_session, void *data, uint32_t datalen, int *payload_type, switch_frame_flag *flags)
|
||||||
{
|
{
|
||||||
switch_size_t bytes;
|
switch_size_t bytes;
|
||||||
|
|
||||||
@ -359,10 +362,16 @@ SWITCH_DECLARE(int) switch_rtp_read(switch_rtp *rtp_session, void *data, uint32_
|
|||||||
}
|
}
|
||||||
memcpy(data, rtp_session->recv_msg.body, bytes);
|
memcpy(data, rtp_session->recv_msg.body, bytes);
|
||||||
*payload_type = rtp_session->recv_msg.header.pt;
|
*payload_type = rtp_session->recv_msg.header.pt;
|
||||||
|
|
||||||
|
if (*payload_type == SWITCH_RTP_CNG_PAYLOAD) {
|
||||||
|
*flags |= SFF_CNG;
|
||||||
|
}
|
||||||
|
|
||||||
return (int)(bytes - rtp_header_len);
|
return (int)(bytes - rtp_header_len);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(int) switch_rtp_zerocopy_read(switch_rtp *rtp_session, void **data, int *payload_type)
|
SWITCH_DECLARE(int) switch_rtp_zerocopy_read(switch_rtp *rtp_session, void **data, int *payload_type, switch_frame_flag *flags)
|
||||||
{
|
{
|
||||||
switch_size_t bytes;
|
switch_size_t bytes;
|
||||||
|
|
||||||
@ -391,6 +400,10 @@ SWITCH_DECLARE(int) switch_rtp_zerocopy_read(switch_rtp *rtp_session, void **dat
|
|||||||
*payload_type = rtp_session->recv_msg.header.pt;
|
*payload_type = rtp_session->recv_msg.header.pt;
|
||||||
*data = rtp_session->recv_msg.body;
|
*data = rtp_session->recv_msg.body;
|
||||||
|
|
||||||
|
if (*payload_type == SWITCH_RTP_CNG_PAYLOAD) {
|
||||||
|
*flags |= SFF_CNG;
|
||||||
|
}
|
||||||
|
|
||||||
return (int)(bytes - rtp_header_len);
|
return (int)(bytes - rtp_header_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,7 +423,7 @@ SWITCH_DECLARE(int) switch_rtp_write(switch_rtp *rtp_session, void *data, int da
|
|||||||
rtp_session->payload = htonl(rtp_session->payload);
|
rtp_session->payload = htonl(rtp_session->payload);
|
||||||
|
|
||||||
memcpy(rtp_session->send_msg.body, data, datalen);
|
memcpy(rtp_session->send_msg.body, data, datalen);
|
||||||
|
|
||||||
bytes = datalen + rtp_header_len;
|
bytes = datalen + rtp_header_len;
|
||||||
switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void*)&rtp_session->send_msg, &bytes);
|
switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void*)&rtp_session->send_msg, &bytes);
|
||||||
if (rtp_session->ice_user) {
|
if (rtp_session->ice_user) {
|
||||||
@ -435,6 +448,7 @@ SWITCH_DECLARE(int) switch_rtp_write_payload(switch_rtp *rtp_session, void *data
|
|||||||
rtp_session->send_msg.header.pt = (uint8_t)htonl(payload);
|
rtp_session->send_msg.header.pt = (uint8_t)htonl(payload);
|
||||||
|
|
||||||
memcpy(rtp_session->send_msg.body, data, datalen);
|
memcpy(rtp_session->send_msg.body, data, datalen);
|
||||||
|
|
||||||
bytes = datalen + rtp_header_len;
|
bytes = datalen + rtp_header_len;
|
||||||
switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void*)&rtp_session->send_msg, &bytes);
|
switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void*)&rtp_session->send_msg, &bytes);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user