2012-08-08 14:46:38 -05:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
* Copyright ( C ) 2005 - 2011 , Anthony Minessale II < anthm @ freeswitch . org >
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II < anthm @ freeswitch . org >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Mathieu Rene < mrene @ avgs . ca >
*
* rtp . c - - RTP Controllable Channel Module
*
*/
# include <switch.h>
# include "mod_sofia.h"
# define kLOCALADDR "local_addr"
# define kLOCALPORT "local_port"
# define kREMOTEADDR "remote_addr"
# define kREMOTEPORT "remote_port"
# define kCODEC "codec"
# define kPTIME "ptime"
# define kPT "pt"
# define kRFC2833PT "rfc2833_pt"
# define kMODE "mode"
# define kRATE "rate"
static struct {
switch_memory_pool_t * pool ;
switch_endpoint_interface_t * endpoint_interface ;
} crtp ;
typedef struct {
switch_core_session_t * session ;
switch_channel_t * channel ;
switch_codec_t read_codec , write_codec ;
switch_frame_t read_frame ;
switch_rtp_bug_flag_t rtp_bugs ;
switch_rtp_t * rtp_session ;
uint32_t timestamp_send ;
const char * local_address ;
const char * remote_address ;
const char * codec ;
int ptime ;
const switch_codec_implementation_t * negotiated_codecs [ SWITCH_MAX_CODECS ] ;
int num_negotiated_codecs ;
char * origin ;
switch_port_t local_port ;
switch_port_t remote_port ;
switch_payload_t agreed_pt ; /*XXX*/
2012-12-20 22:57:47 -06:00
switch_core_media_dtmf_t dtmf_type ;
2012-08-08 14:46:38 -05:00
enum {
RTP_SENDONLY ,
RTP_RECVONLY ,
RTP_SENDRECV
} mode ;
} crtp_private_t ;
static switch_status_t channel_on_init ( switch_core_session_t * session ) ;
static switch_status_t channel_on_destroy ( switch_core_session_t * session ) ;
static switch_call_cause_t channel_outgoing_channel ( switch_core_session_t * session , switch_event_t * var_event ,
switch_caller_profile_t * outbound_profile ,
switch_core_session_t * * new_session ,
switch_memory_pool_t * * pool ,
switch_originate_flag_t flags , switch_call_cause_t * cancel_cause ) ;
static switch_status_t channel_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id ) ;
static switch_status_t channel_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id ) ;
static switch_status_t channel_receive_message ( switch_core_session_t * session , switch_core_session_message_t * msg ) ;
static switch_status_t channel_send_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf ) ;
static switch_status_t channel_receive_event ( switch_core_session_t * session , switch_event_t * event ) ;
switch_state_handler_table_t crtp_state_handlers = {
2012-08-08 21:18:06 -05:00
/*on_init */ channel_on_init ,
/*on_routing */ NULL ,
/*on_execute */ NULL ,
/*on_hangup*/ NULL ,
/*on_exchange_media*/ NULL ,
/*on_soft_execute*/ NULL ,
/*on_consume_media*/ NULL ,
/*on_hibernate*/ NULL ,
/*on_reset*/ NULL ,
/*on_park*/ NULL ,
/*on_reporting*/ NULL ,
/*on_destroy*/ channel_on_destroy
2012-08-08 14:46:38 -05:00
} ;
switch_io_routines_t crtp_io_routines = {
2012-08-08 21:18:06 -05:00
/*outgoing_channel*/ channel_outgoing_channel ,
/*read_frame*/ channel_read_frame ,
/*write_frame*/ channel_write_frame ,
/*kill_channel*/ NULL ,
/*send_dtmf*/ channel_send_dtmf ,
/*receive_message*/ channel_receive_message ,
/*receive_event*/ channel_receive_event ,
/*state_change*/ NULL ,
/*read_video_frame*/ NULL ,
/*write_video_frame*/ NULL ,
2012-08-22 14:27:27 -05:00
/*state_run*/ NULL
2012-08-08 21:18:06 -05:00
2012-08-08 14:46:38 -05:00
} ;
void crtp_init ( switch_loadable_module_interface_t * module_interface )
{
switch_endpoint_interface_t * endpoint_interface ;
//switch_api_interface_t *api_interface;
crtp . pool = module_interface - > pool ;
endpoint_interface = switch_loadable_module_create_interface ( module_interface , SWITCH_ENDPOINT_INTERFACE ) ;
endpoint_interface - > interface_name = " rtp " ;
endpoint_interface - > io_routines = & crtp_io_routines ;
endpoint_interface - > state_handler = & crtp_state_handlers ;
crtp . endpoint_interface = endpoint_interface ;
//SWITCH_ADD_API(api_interface, "rtp_test", "test", test_function, "");
}
static switch_call_cause_t channel_outgoing_channel ( switch_core_session_t * session , switch_event_t * var_event ,
switch_caller_profile_t * outbound_profile ,
switch_core_session_t * * new_session ,
switch_memory_pool_t * * pool ,
switch_originate_flag_t flags , switch_call_cause_t * cancel_cause )
{
switch_channel_t * channel ;
char name [ 128 ] ;
crtp_private_t * tech_pvt = NULL ;
switch_caller_profile_t * caller_profile ;
const char * err ;
const char * local_addr = switch_event_get_header_nil ( var_event , kLOCALADDR ) ,
* szlocal_port = switch_event_get_header_nil ( var_event , kLOCALPORT ) ,
* remote_addr = switch_event_get_header_nil ( var_event , kREMOTEADDR ) ,
* szremote_port = switch_event_get_header_nil ( var_event , kREMOTEPORT ) ,
* codec = switch_event_get_header_nil ( var_event , kCODEC ) ,
* szptime = switch_event_get_header_nil ( var_event , kPTIME ) ,
//*mode = switch_event_get_header_nil(var_event, kMODE),
//*szrfc2833_pt = switch_event_get_header_nil(var_event, kRFC2833PT),
* szrate = switch_event_get_header_nil ( var_event , kRATE ) ,
* szpt = switch_event_get_header_nil ( var_event , kPT ) ;
switch_port_t local_port = ! zstr ( szlocal_port ) ? atoi ( szlocal_port ) : 0 ,
remote_port = ! zstr ( szremote_port ) ? atoi ( szremote_port ) : 0 ;
int ptime = ! zstr ( szptime ) ? atoi ( szptime ) : 0 ,
//rfc2833_pt = !zstr(szrfc2833_pt) ? atoi(szrfc2833_pt) : 0,
rate = ! zstr ( szrate ) ? atoi ( szrate ) : 8000 ,
pt = ! zstr ( szpt ) ? atoi ( szpt ) : 0 ;
if (
( ( zstr ( remote_addr ) | | remote_port = = 0 ) & & ( zstr ( local_addr ) | | local_port = = 0 ) ) | |
zstr ( codec ) | |
zstr ( szpt ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing required arguments \n " ) ;
goto fail ;
}
if ( ! ( * new_session = switch_core_session_request ( crtp . endpoint_interface , SWITCH_CALL_DIRECTION_OUTBOUND , 0 , pool ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't request session. \n " ) ;
goto fail ;
}
channel = switch_core_session_get_channel ( * new_session ) ;
tech_pvt = switch_core_session_alloc ( * new_session , sizeof * tech_pvt ) ;
tech_pvt - > session = * new_session ;
tech_pvt - > channel = channel ;
tech_pvt - > local_address = switch_core_session_strdup ( * new_session , local_addr ) ;
tech_pvt - > local_port = local_port ;
tech_pvt - > remote_address = switch_core_session_strdup ( * new_session , remote_addr ) ;
tech_pvt - > remote_port = remote_port ;
tech_pvt - > ptime = ptime ;
tech_pvt - > agreed_pt = pt ;
tech_pvt - > dtmf_type = DTMF_2833 ; /* XXX */
if ( zstr ( local_addr ) | | local_port = = 0 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " The local address and port must be set \n " ) ;
goto fail ;
} else if ( zstr ( remote_addr ) | | remote_port = = 0 ) {
tech_pvt - > mode = RTP_RECVONLY ;
} else {
tech_pvt - > mode = RTP_SENDRECV ;
}
switch_core_session_set_private ( * new_session , tech_pvt ) ;
caller_profile = switch_caller_profile_clone ( * new_session , outbound_profile ) ;
switch_channel_set_caller_profile ( channel , caller_profile ) ;
snprintf ( name , sizeof ( name ) , " rtp/%s " , outbound_profile - > destination_number ) ;
switch_channel_set_name ( channel , name ) ;
switch_channel_set_state ( channel , CS_INIT ) ;
if ( switch_core_codec_init ( & tech_pvt - > read_codec ,
codec ,
NULL ,
rate ,
ptime ,
1 ,
/*SWITCH_CODEC_FLAG_ENCODE |*/ SWITCH_CODEC_FLAG_DECODE ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
goto fail ;
} else {
if ( switch_core_codec_init ( & tech_pvt - > write_codec ,
codec ,
NULL ,
rate ,
ptime ,
1 ,
SWITCH_CODEC_FLAG_ENCODE /*| SWITCH_CODEC_FLAG_DECODE*/ ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
goto fail ;
}
}
if ( switch_core_session_set_read_codec ( * new_session , & tech_pvt - > read_codec ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't set read codec? \n " ) ;
goto fail ;
}
if ( switch_core_session_set_write_codec ( * new_session , & tech_pvt - > write_codec ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't set write codec? \n " ) ;
goto fail ;
}
if ( ! ( tech_pvt - > rtp_session = switch_rtp_new ( local_addr , local_port , remote_addr , remote_port , tech_pvt - > agreed_pt ,
2012-12-18 16:06:29 -06:00
tech_pvt - > read_codec . implementation - > samples_per_packet , ptime * 1000 ,
0 , " soft " , & err , switch_core_session_get_pool ( * new_session ) ) ) ) {
2012-08-08 14:46:38 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't setup RTP session: [%s] \n " , err ) ;
goto fail ;
}
if ( switch_core_session_thread_launch ( * new_session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't start session thread. \n " ) ;
goto fail ;
}
switch_channel_mark_answered ( channel ) ;
return SWITCH_CAUSE_SUCCESS ;
fail :
if ( tech_pvt ) {
if ( tech_pvt - > read_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
}
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
}
if ( * new_session ) {
switch_core_session_destroy ( new_session ) ;
}
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
static switch_status_t channel_on_init ( switch_core_session_t * session )
{
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
switch_channel_set_state ( channel , CS_CONSUME_MEDIA ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_on_destroy ( switch_core_session_t * session )
{
crtp_private_t * tech_pvt = switch_core_session_get_private ( session ) ;
if ( ( tech_pvt = switch_core_session_get_private ( session ) ) ) {
if ( tech_pvt - > read_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
}
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
}
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id )
{
crtp_private_t * tech_pvt ;
switch_channel_t * channel ;
switch_status_t status ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
if ( ! tech_pvt - > rtp_session | | tech_pvt - > mode = = RTP_SENDONLY ) {
switch_yield ( 20000 ) ; /* replace by local timer XXX */
goto cng ;
}
if ( switch_rtp_has_dtmf ( tech_pvt - > rtp_session ) ) {
switch_dtmf_t dtmf = { 0 } ;
switch_rtp_dequeue_dtmf ( tech_pvt - > rtp_session , & dtmf ) ;
switch_channel_queue_dtmf ( channel , & dtmf ) ;
}
tech_pvt - > read_frame . flags = SFF_NONE ;
tech_pvt - > read_frame . codec = & tech_pvt - > read_codec ;
status = switch_rtp_zerocopy_read_frame ( tech_pvt - > rtp_session , & tech_pvt - > read_frame , flags ) ;
if ( status ! = SWITCH_STATUS_SUCCESS & & status ! = SWITCH_STATUS_BREAK ) {
goto cng ;
}
* frame = & tech_pvt - > read_frame ;
return SWITCH_STATUS_SUCCESS ;
cng :
* frame = & tech_pvt - > read_frame ;
tech_pvt - > read_frame . codec = & tech_pvt - > read_codec ;
tech_pvt - > read_frame . flags | = SFF_CNG ;
tech_pvt - > read_frame . datalen = 0 ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id )
{
crtp_private_t * tech_pvt ;
switch_channel_t * channel ;
//int frames = 0, bytes = 0, samples = 0;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
#if 0
if ( ! switch_test_flag ( frame , SFF_CNG ) & & ! switch_test_flag ( frame , SFF_PROXY_PACKET ) ) {
if ( tech_pvt - > read_codec . implementation - > encoded_bytes_per_packet ) {
bytes = tech_pvt - > read_codec . implementation - > encoded_bytes_per_packet ;
frames = ( ( int ) frame - > datalen / bytes ) ;
} else
frames = 1 ;
samples = frames * tech_pvt - > read_codec . implementation - > samples_per_packet ;
}
tech_pvt - > timestamp_send + = samples ;
# endif
if ( tech_pvt - > mode = = RTP_RECVONLY ) {
return SWITCH_STATUS_SUCCESS ;
}
switch_rtp_write_frame ( tech_pvt - > rtp_session , frame ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_send_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf )
{
crtp_private_t * tech_pvt = NULL ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch ( tech_pvt - > dtmf_type ) {
case DTMF_2833 :
{
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Enqueuing RFC2833 DTMF %c of length %d \n " , dtmf - > digit , dtmf - > duration ) ;
return switch_rtp_queue_rfc2833 ( tech_pvt - > rtp_session , dtmf ) ;
}
case DTMF_NONE :
default :
{
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Discarding DTMF %c of length %d, DTMF type is NONE \n " , dtmf - > digit , dtmf - > duration ) ;
}
}
return SWITCH_STATUS_SUCCESS ;
}
static switch_bool_t compare_var ( switch_event_t * event , switch_channel_t * channel , const char * varname )
{
const char * chan_val = switch_channel_get_variable_dup ( channel , varname , SWITCH_FALSE , - 1 ) ;
const char * event_val = switch_event_get_header ( event , varname ) ;
if ( zstr ( chan_val ) | | zstr ( event_val ) ) {
return 1 ;
}
return strcasecmp ( chan_val , event_val ) ;
}
static switch_status_t channel_receive_event ( switch_core_session_t * session , switch_event_t * event )
{
const char * command = switch_event_get_header ( event , " command " ) ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
crtp_private_t * tech_pvt = switch_core_session_get_private ( session ) ;
char * codec = switch_event_get_header_nil ( event , kCODEC ) ;
char * szptime = switch_event_get_header_nil ( event , kPTIME ) ;
char * szrate = switch_event_get_header_nil ( event , kRATE ) ;
char * szpt = switch_event_get_header_nil ( event , kPT ) ;
int ptime = ! zstr ( szptime ) ? atoi ( szptime ) : 0 ,
rate = ! zstr ( szrate ) ? atoi ( szrate ) : 8000 ,
pt = ! zstr ( szpt ) ? atoi ( szpt ) : 0 ;
if ( ! zstr ( command ) & & ! strcasecmp ( command , " media_modify " ) ) {
/* Compare parameters */
if ( compare_var ( event , channel , kREMOTEADDR ) | |
compare_var ( event , channel , kREMOTEPORT ) ) {
char * remote_addr = switch_event_get_header ( event , kREMOTEADDR ) ;
char * szremote_port = switch_event_get_header ( event , kREMOTEPORT ) ;
switch_port_t remote_port = ! zstr ( szremote_port ) ? atoi ( szremote_port ) : 0 ;
const char * err ;
switch_channel_set_variable ( channel , kREMOTEADDR , remote_addr ) ;
switch_channel_set_variable ( channel , kREMOTEPORT , szremote_port ) ;
if ( switch_rtp_set_remote_address ( tech_pvt - > rtp_session , remote_addr , remote_port , 0 , SWITCH_TRUE , & err ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Error setting RTP remote address: %s \n " , err ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Set RTP remote: %s:%d \n " , remote_addr , ( int ) remote_port ) ;
tech_pvt - > mode = RTP_SENDRECV ;
}
}
if ( compare_var ( event , channel , kCODEC ) | |
compare_var ( event , channel , kPTIME ) | |
compare_var ( event , channel , kPT ) | |
compare_var ( event , channel , kRATE ) ) {
/* Reset codec */
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_CRIT , " Switching codec updating \n " ) ;
if ( switch_core_codec_init ( & tech_pvt - > read_codec ,
codec ,
NULL ,
rate ,
ptime ,
1 ,
/*SWITCH_CODEC_FLAG_ENCODE |*/ SWITCH_CODEC_FLAG_DECODE ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
goto fail ;
} else {
if ( switch_core_codec_init ( & tech_pvt - > write_codec ,
codec ,
NULL ,
rate ,
ptime ,
1 ,
SWITCH_CODEC_FLAG_ENCODE /*| SWITCH_CODEC_FLAG_DECODE*/ ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
goto fail ;
}
}
if ( switch_core_session_set_read_codec ( session , & tech_pvt - > read_codec ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't set read codec? \n " ) ;
goto fail ;
}
if ( switch_core_session_set_write_codec ( session , & tech_pvt - > write_codec ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't set write codec? \n " ) ;
goto fail ;
}
switch_rtp_set_default_payload ( tech_pvt - > rtp_session , pt ) ;
switch_rtp_set_recv_pt ( tech_pvt - > rtp_session , pt ) ;
}
if ( compare_var ( event , channel , kRFC2833PT ) ) {
const char * szpt = switch_channel_get_variable ( channel , kRFC2833PT ) ;
int pt = ! zstr ( szpt ) ? atoi ( szpt ) : 0 ;
switch_channel_set_variable ( channel , kRFC2833PT , szpt ) ;
switch_rtp_set_telephony_event ( tech_pvt - > rtp_session , pt ) ;
}
} else {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Received unknown command [%s] in event. \n " , ! command ? " null " : command ) ;
}
return SWITCH_STATUS_SUCCESS ;
fail :
if ( tech_pvt ) {
if ( tech_pvt - > read_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
}
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
}
if ( session ) {
switch_core_session_destroy ( & session ) ;
}
2012-08-11 16:19:11 -04:00
return SWITCH_STATUS_FALSE ;
2012-08-08 14:46:38 -05:00
}
static switch_status_t channel_receive_message ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
crtp_private_t * tech_pvt = NULL ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_DEBUG_AUDIO :
{
if ( switch_rtp_ready ( tech_pvt - > rtp_session ) & & ! zstr ( msg - > string_array_arg [ 0 ] ) & & ! zstr ( msg - > string_array_arg [ 1 ] ) ) {
2012-12-18 16:06:29 -06:00
switch_rtp_flag_t flags [ SWITCH_RTP_FLAG_INVALID ] = { 0 } ;
int x = 0 ;
2012-08-08 14:46:38 -05:00
if ( ! strcasecmp ( msg - > string_array_arg [ 0 ] , " read " ) ) {
2012-12-18 16:06:29 -06:00
flags [ SWITCH_RTP_FLAG_DEBUG_RTP_READ ] + + ; x + + ;
2012-08-08 14:46:38 -05:00
} else if ( ! strcasecmp ( msg - > string_array_arg [ 0 ] , " write " ) ) {
2012-12-18 16:06:29 -06:00
flags [ SWITCH_RTP_FLAG_DEBUG_RTP_WRITE ] + + ; x + + ;
2012-08-08 14:46:38 -05:00
} else if ( ! strcasecmp ( msg - > string_array_arg [ 0 ] , " both " ) ) {
2012-12-18 16:06:29 -06:00
flags [ SWITCH_RTP_FLAG_DEBUG_RTP_READ ] + + ; x + + ;
flags [ SWITCH_RTP_FLAG_DEBUG_RTP_WRITE ] + + ;
2012-08-08 14:46:38 -05:00
}
2012-12-18 16:06:29 -06:00
if ( x ) {
2012-08-08 14:46:38 -05:00
if ( switch_true ( msg - > string_array_arg [ 1 ] ) ) {
2012-12-18 16:06:29 -06:00
switch_rtp_set_flags ( tech_pvt - > rtp_session , flags ) ;
2012-08-08 14:46:38 -05:00
} else {
2012-12-18 16:06:29 -06:00
switch_rtp_clear_flags ( tech_pvt - > rtp_session , flags ) ;
2012-08-08 14:46:38 -05:00
}
} else {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Invalid Options \n " ) ;
}
}
break ;
}
case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC :
if ( switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
rtp_flush_read_buffer ( tech_pvt - > rtp_session , SWITCH_RTP_FLUSH_ONCE ) ;
}
break ;
case SWITCH_MESSAGE_INDICATE_JITTER_BUFFER :
{
if ( switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
int len = 0 , maxlen = 0 , qlen = 0 , maxqlen = 50 , max_drift = 0 ;
if ( msg - > string_arg ) {
char * p , * q ;
const char * s ;
if ( ! strcasecmp ( msg - > string_arg , " pause " ) ) {
switch_rtp_pause_jitter_buffer ( tech_pvt - > rtp_session , SWITCH_TRUE ) ;
goto end ;
} else if ( ! strcasecmp ( msg - > string_arg , " resume " ) ) {
switch_rtp_pause_jitter_buffer ( tech_pvt - > rtp_session , SWITCH_FALSE ) ;
goto end ;
} else if ( ! strncasecmp ( msg - > string_arg , " debug: " , 6 ) ) {
s = msg - > string_arg + 6 ;
if ( s & & ! strcmp ( s , " off " ) ) {
s = NULL ;
}
switch_rtp_debug_jitter_buffer ( tech_pvt - > rtp_session , s ) ;
goto end ;
}
if ( ( len = atoi ( msg - > string_arg ) ) ) {
qlen = len / ( tech_pvt - > read_codec . implementation - > microseconds_per_packet / 1000 ) ;
if ( qlen < 1 ) {
qlen = 3 ;
}
}
if ( qlen ) {
if ( ( p = strchr ( msg - > string_arg , ' : ' ) ) ) {
p + + ;
maxlen = atol ( p ) ;
if ( ( q = strchr ( p , ' : ' ) ) ) {
q + + ;
max_drift = abs ( atol ( q ) ) ;
}
}
}
if ( maxlen ) {
maxqlen = maxlen / ( tech_pvt - > read_codec . implementation - > microseconds_per_packet / 1000 ) ;
}
}
if ( qlen ) {
if ( maxqlen < qlen ) {
maxqlen = qlen * 5 ;
}
if ( switch_rtp_activate_jitter_buffer ( tech_pvt - > rtp_session , qlen , maxqlen ,
tech_pvt - > read_codec . implementation - > samples_per_packet ,
tech_pvt - > read_codec . implementation - > samples_per_second , max_drift ) = = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( tech_pvt - > session ) ,
SWITCH_LOG_DEBUG , " Setting Jitterbuffer to %dms (%d frames) (%d max frames) (%d max drift) \n " ,
len , qlen , maxqlen , max_drift ) ;
switch_channel_set_flag ( tech_pvt - > channel , CF_JITTERBUFFER ) ;
if ( ! switch_false ( switch_channel_get_variable ( tech_pvt - > channel , " sip_jitter_buffer_plc " ) ) ) {
switch_channel_set_flag ( tech_pvt - > channel , CF_JITTERBUFFER_PLC ) ;
}
} else {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( tech_pvt - > session ) ,
SWITCH_LOG_WARNING , " Error Setting Jitterbuffer to %dms (%d frames) \n " , len , qlen ) ;
}
} else {
switch_rtp_deactivate_jitter_buffer ( tech_pvt - > rtp_session ) ;
}
}
}
break ;
default :
break ;
}
end :
return SWITCH_STATUS_SUCCESS ;
}