2007-03-29 22:34:40 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2009-02-13 23:37:37 +00:00
* Copyright ( C ) 2005 - 2009 , Anthony Minessale II < anthm @ freeswitch . org >
2007-03-29 22:34:40 +00:00
*
* 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
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2007-03-29 22:34:40 +00:00
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2007-03-29 22:34:40 +00:00
* Michael Jerris < mike @ jerris . com >
* Paul D . Tinsley < pdt at jackhammer . org >
*
*
* switch_core_io . c - - Main Core Library ( Media I / O )
*
*/
2008-01-27 17:36:53 +00:00
2007-03-29 22:34:40 +00:00
# include <switch.h>
2007-05-14 17:10:46 +00:00
# include "private/switch_core_pvt.h"
2007-03-29 22:34:40 +00:00
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_core_session_write_video_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags ,
int stream_id )
2007-04-19 21:40:50 +00:00
{
switch_io_event_hook_video_write_frame_t * ptr ;
switch_status_t status = SWITCH_STATUS_FALSE ;
2008-03-10 19:04:01 +00:00
2009-02-25 03:41:18 +00:00
if ( switch_channel_down ( session - > channel ) ) {
2008-03-10 19:04:01 +00:00
return SWITCH_STATUS_FALSE ;
}
2007-04-19 21:40:50 +00:00
if ( session - > endpoint_interface - > io_routines - > write_video_frame ) {
2008-05-08 19:19:47 +00:00
if ( ( status = session - > endpoint_interface - > io_routines - > write_video_frame ( session , frame , flags , stream_id ) ) = = SWITCH_STATUS_SUCCESS ) {
2007-04-19 21:40:50 +00:00
for ( ptr = session - > event_hooks . video_write_frame ; ptr ; ptr = ptr - > next ) {
2008-05-08 19:19:47 +00:00
if ( ( status = ptr - > video_write_frame ( session , frame , flags , stream_id ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-04-19 21:40:50 +00:00
break ;
}
}
}
}
return status ;
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_core_session_read_video_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags ,
int stream_id )
2007-04-19 21:40:50 +00:00
{
switch_status_t status = SWITCH_STATUS_FALSE ;
switch_io_event_hook_video_read_frame_t * ptr ;
2008-05-16 14:43:21 +00:00
switch_assert ( session ! = NULL ) ;
2009-02-25 03:41:18 +00:00
if ( switch_channel_down ( session - > channel ) ) {
2008-03-10 19:04:01 +00:00
return SWITCH_STATUS_FALSE ;
}
2007-04-19 21:40:50 +00:00
if ( session - > endpoint_interface - > io_routines - > read_video_frame ) {
2008-05-27 04:30:03 +00:00
if ( ( status = session - > endpoint_interface - > io_routines - > read_video_frame ( session , frame , flags , stream_id ) ) = = SWITCH_STATUS_SUCCESS ) {
2007-04-19 21:40:50 +00:00
for ( ptr = session - > event_hooks . video_read_frame ; ptr ; ptr = ptr - > next ) {
2008-05-08 19:19:47 +00:00
if ( ( status = ptr - > video_read_frame ( session , frame , flags , stream_id ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-04-19 21:40:50 +00:00
break ;
}
}
}
}
if ( status ! = SWITCH_STATUS_SUCCESS ) {
goto done ;
}
if ( ! ( * frame ) ) {
goto done ;
}
2007-12-11 19:23:57 +00:00
switch_assert ( * frame ! = NULL ) ;
2007-04-19 21:40:50 +00:00
if ( switch_test_flag ( * frame , SFF_CNG ) ) {
status = SWITCH_STATUS_SUCCESS ;
goto done ;
}
2008-05-27 04:30:03 +00:00
done :
2007-04-19 21:40:50 +00:00
return status ;
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_core_session_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags ,
int stream_id )
2007-03-29 22:34:40 +00:00
{
switch_io_event_hook_read_frame_t * ptr ;
2008-11-19 20:12:20 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2008-01-03 21:34:44 +00:00
int need_codec , perfect , do_bugs = 0 , do_resample = 0 , is_cng = 0 ;
2007-03-29 22:34:40 +00:00
unsigned int flag = 0 ;
2009-04-09 17:17:12 +00:00
switch_codec_implementation_t codec_impl ;
2008-05-08 20:58:25 +00:00
2008-05-16 14:43:21 +00:00
switch_assert ( session ! = NULL ) ;
2009-04-09 17:17:12 +00:00
if ( ! ( session - > read_codec & & session - > read_codec - > implementation & & switch_core_codec_ready ( session - > read_codec ) ) ) {
2008-11-21 00:09:11 +00:00
if ( switch_channel_test_flag ( session - > channel , CF_PROXY_MODE ) | | switch_channel_get_state ( session - > channel ) = = CS_HIBERNATE ) {
* frame = & runtime . dummy_cng_frame ;
return SWITCH_STATUS_SUCCESS ;
}
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " %s has no read codec. \n " , switch_channel_get_name ( session - > channel ) ) ;
2008-11-19 20:12:20 +00:00
return SWITCH_STATUS_FALSE ;
}
2008-11-21 00:09:11 +00:00
switch_mutex_lock ( session - > codec_read_mutex ) ;
2008-11-19 20:12:20 +00:00
switch_mutex_lock ( session - > read_codec - > mutex ) ;
2008-05-27 04:30:03 +00:00
top :
2007-03-29 22:34:40 +00:00
2009-02-25 03:41:18 +00:00
if ( switch_channel_down ( session - > channel ) ) {
2008-03-18 21:40:32 +00:00
* frame = NULL ;
2008-11-19 20:12:20 +00:00
status = SWITCH_STATUS_FALSE ; goto even_more_done ;
2008-03-10 19:04:01 +00:00
}
2007-03-29 22:34:40 +00:00
status = SWITCH_STATUS_FALSE ;
need_codec = perfect = 0 ;
* frame = NULL ;
2008-10-21 16:22:38 +00:00
if ( session - > read_codec & & ! session - > track_id & & session - > track_duration ) {
2008-10-07 21:03:37 +00:00
if ( session - > read_frame_count = = 0 ) {
switch_event_t * event ;
2009-01-15 16:54:13 +00:00
session - > read_frame_count = ( session - > read_impl . actual_samples_per_second /
session - > read_impl . samples_per_packet ) * session - > track_duration ;
2008-10-07 21:03:37 +00:00
switch_event_create ( & event , SWITCH_EVENT_SESSION_HEARTBEAT ) ;
switch_channel_event_set_data ( session - > channel , event ) ;
switch_event_fire ( & event ) ;
} else {
session - > read_frame_count - - ;
}
}
2007-03-29 22:34:40 +00:00
if ( switch_channel_test_flag ( session - > channel , CF_HOLD ) ) {
2009-01-15 16:54:13 +00:00
switch_yield ( session - > read_impl . microseconds_per_packet ) ;
2007-03-29 22:34:40 +00:00
status = SWITCH_STATUS_BREAK ;
2008-05-01 16:41:46 +00:00
goto even_more_done ;
2007-03-29 22:34:40 +00:00
}
if ( session - > endpoint_interface - > io_routines - > read_frame ) {
2008-11-21 16:14:02 +00:00
switch_mutex_unlock ( session - > read_codec - > mutex ) ;
switch_mutex_unlock ( session - > codec_read_mutex ) ;
2008-05-27 04:30:03 +00:00
if ( ( status = session - > endpoint_interface - > io_routines - > read_frame ( session , frame , flags , stream_id ) ) = = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
for ( ptr = session - > event_hooks . read_frame ; ptr ; ptr = ptr - > next ) {
2008-05-08 19:19:47 +00:00
if ( ( status = ptr - > read_frame ( session , frame , flags , stream_id ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
break ;
}
}
}
2008-11-21 16:14:02 +00:00
2008-11-25 19:05:00 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( status ) | | ! session - > read_codec | | ! session - > read_codec - > mutex ) {
2008-11-21 16:14:02 +00:00
* frame = NULL ;
return SWITCH_STATUS_FALSE ;
}
switch_mutex_lock ( session - > codec_read_mutex ) ;
switch_mutex_lock ( session - > read_codec - > mutex ) ;
2007-03-29 22:34:40 +00:00
}
if ( status ! = SWITCH_STATUS_SUCCESS ) {
goto done ;
}
if ( ! ( * frame ) ) {
goto done ;
}
2007-12-11 19:23:57 +00:00
switch_assert ( * frame ! = NULL ) ;
2007-03-29 22:34:40 +00:00
2008-02-21 17:48:41 +00:00
if ( switch_test_flag ( * frame , SFF_PROXY_PACKET ) ) {
/* Fast PASS! */
status = SWITCH_STATUS_SUCCESS ;
goto done ;
2008-05-27 04:30:03 +00:00
}
2008-02-21 17:48:41 +00:00
2007-03-29 22:34:40 +00:00
if ( switch_test_flag ( * frame , SFF_CNG ) ) {
status = SWITCH_STATUS_SUCCESS ;
2008-01-03 21:34:44 +00:00
if ( ! session - > bugs ) {
goto done ;
}
is_cng = 1 ;
2008-05-27 04:30:03 +00:00
}
2007-03-29 22:34:40 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( ( * frame ) - > codec ! = NULL ) ;
2008-05-09 19:59:42 +00:00
2009-04-09 17:17:12 +00:00
if ( ! ( session - > read_codec & & ( * frame ) - > codec & & ( * frame ) - > codec - > implementation ) & & switch_core_codec_ready ( ( * frame ) - > codec ) ) {
2007-03-29 22:34:40 +00:00
status = SWITCH_STATUS_FALSE ;
goto done ;
}
2009-04-09 17:17:12 +00:00
codec_impl = * ( * frame ) - > codec - > implementation ;
if ( session - > read_codec - > implementation - > impl_id ! = codec_impl . impl_id ) {
need_codec = TRUE ;
}
if ( codec_impl . actual_samples_per_second ! = session - > read_impl . actual_samples_per_second ) {
2007-07-02 20:17:10 +00:00
do_resample = 1 ;
}
2007-03-29 22:34:40 +00:00
if ( session - > bugs & & ! need_codec ) {
do_bugs = 1 ;
need_codec = 1 ;
}
if ( status = = SWITCH_STATUS_SUCCESS & & need_codec ) {
switch_frame_t * enc_frame , * read_frame = * frame ;
2008-05-13 20:36:23 +00:00
if ( ! switch_test_flag ( session , SSF_WARN_TRANSCODE ) ) {
switch_core_session_message_t msg = { 0 } ;
2008-05-27 04:30:03 +00:00
2008-05-13 20:36:23 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY ;
switch_core_session_receive_message ( session , & msg ) ;
switch_set_flag ( session , SSF_WARN_TRANSCODE ) ;
}
2008-05-27 04:30:03 +00:00
2008-01-03 21:34:44 +00:00
if ( read_frame - > codec | | is_cng ) {
2007-03-29 22:34:40 +00:00
session - > raw_read_frame . datalen = session - > raw_read_frame . buflen ;
2008-05-27 04:30:03 +00:00
2008-01-03 21:34:44 +00:00
if ( is_cng ) {
2008-10-20 17:48:42 +00:00
memset ( session - > raw_read_frame . data , 255 , read_frame - > codec - > implementation - > decoded_bytes_per_packet ) ;
session - > raw_read_frame . datalen = read_frame - > codec - > implementation - > decoded_bytes_per_packet ;
2008-01-03 21:34:44 +00:00
session - > raw_read_frame . samples = session - > raw_read_frame . datalen / sizeof ( int16_t ) ;
read_frame = & session - > raw_read_frame ;
status = SWITCH_STATUS_SUCCESS ;
} else {
2008-03-17 23:26:38 +00:00
switch_codec_t * use_codec = read_frame - > codec ;
if ( do_bugs ) {
2009-04-09 17:17:12 +00:00
if ( ! switch_core_codec_ready ( & session - > bug_codec ) ) {
2009-08-01 02:47:35 +00:00
switch_core_codec_copy ( read_frame - > codec , & session - > bug_codec , NULL ) ;
2008-03-17 23:26:38 +00:00
}
use_codec = & session - > bug_codec ;
}
status = switch_core_codec_decode ( use_codec ,
2008-01-03 21:34:44 +00:00
session - > read_codec ,
read_frame - > data ,
read_frame - > datalen ,
2009-01-15 16:54:13 +00:00
session - > read_impl . actual_samples_per_second ,
2008-01-03 21:34:44 +00:00
session - > raw_read_frame . data , & session - > raw_read_frame . datalen , & session - > raw_read_frame . rate , & flag ) ;
}
if ( do_resample & & ( ( status = = SWITCH_STATUS_SUCCESS ) | | is_cng ) ) {
2007-07-02 20:17:10 +00:00
status = SWITCH_STATUS_RESAMPLE ;
}
2007-03-29 22:34:40 +00:00
switch ( status ) {
case SWITCH_STATUS_RESAMPLE :
if ( ! session - > read_resampler ) {
2008-01-04 00:19:09 +00:00
switch_mutex_lock ( session - > resample_mutex ) ;
status = switch_resample_create ( & session - > read_resampler ,
read_frame - > codec - > implementation - > actual_samples_per_second ,
2009-02-13 23:35:17 +00:00
session - > read_impl . actual_samples_per_second ,
session - > read_impl . decoded_bytes_per_packet ,
2009-07-23 15:55:13 +00:00
SWITCH_RESAMPLE_QUALITY , 1 ) ;
2009-02-13 23:35:17 +00:00
2008-01-04 00:19:09 +00:00
switch_mutex_unlock ( session - > resample_mutex ) ;
2008-05-27 04:30:03 +00:00
2008-01-04 00:19:09 +00:00
if ( status ! = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Unable to allocate resampler \n " ) ;
2007-03-29 22:34:40 +00:00
status = SWITCH_STATUS_FALSE ;
goto done ;
}
}
case SWITCH_STATUS_SUCCESS :
session - > raw_read_frame . samples = session - > raw_read_frame . datalen / sizeof ( int16_t ) ;
session - > raw_read_frame . rate = read_frame - > rate ;
2009-01-15 16:54:13 +00:00
if ( read_frame - > codec - > implementation - > samples_per_packet ! = session - > read_impl . samples_per_packet ) {
2008-11-13 07:36:06 +00:00
session - > raw_read_frame . timestamp = 0 ;
} else {
session - > raw_read_frame . timestamp = read_frame - > timestamp ;
}
2007-04-19 21:40:50 +00:00
session - > raw_read_frame . ssrc = read_frame - > ssrc ;
session - > raw_read_frame . seq = read_frame - > seq ;
session - > raw_read_frame . m = read_frame - > m ;
session - > raw_read_frame . payload = read_frame - > payload ;
2007-03-29 22:34:40 +00:00
read_frame = & session - > raw_read_frame ;
break ;
case SWITCH_STATUS_NOOP :
2007-12-13 00:43:59 +00:00
if ( session - > read_resampler ) {
2008-01-04 00:19:09 +00:00
switch_mutex_lock ( session - > resample_mutex ) ;
2007-12-13 00:43:59 +00:00
switch_resample_destroy ( & session - > read_resampler ) ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_NOTICE , " Deactivating read resampler \n " ) ;
2008-05-27 04:30:03 +00:00
switch_mutex_unlock ( session - > resample_mutex ) ;
2007-12-13 00:43:59 +00:00
}
2007-03-29 22:34:40 +00:00
status = SWITCH_STATUS_SUCCESS ;
break ;
2007-03-30 16:41:12 +00:00
case SWITCH_STATUS_BREAK :
2008-10-20 17:48:42 +00:00
memset ( session - > raw_read_frame . data , 255 , read_frame - > codec - > implementation - > decoded_bytes_per_packet ) ;
session - > raw_read_frame . datalen = read_frame - > codec - > implementation - > decoded_bytes_per_packet ;
2007-03-30 16:41:12 +00:00
session - > raw_read_frame . samples = session - > raw_read_frame . datalen / sizeof ( int16_t ) ;
session - > raw_read_frame . timestamp = read_frame - > timestamp ;
session - > raw_read_frame . rate = read_frame - > rate ;
2007-04-19 21:40:50 +00:00
session - > raw_read_frame . ssrc = read_frame - > ssrc ;
session - > raw_read_frame . seq = read_frame - > seq ;
session - > raw_read_frame . m = read_frame - > m ;
session - > raw_read_frame . payload = read_frame - > payload ;
2007-03-30 16:41:12 +00:00
read_frame = & session - > raw_read_frame ;
status = SWITCH_STATUS_SUCCESS ;
break ;
2008-10-29 00:04:20 +00:00
case SWITCH_STATUS_NOT_INITALIZED :
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Codec init error! \n " ) ;
2008-10-29 00:04:20 +00:00
goto done ;
2007-03-29 22:34:40 +00:00
default :
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Codec %s decoder error! \n " , session - > read_codec - > codec_interface - > interface_name ) ;
2007-03-29 22:34:40 +00:00
goto done ;
}
}
2009-01-26 16:47:00 +00:00
if ( session - > bugs & & ! switch_channel_test_flag ( session - > channel , CF_PAUSE_BUGS ) ) {
2007-03-29 22:34:40 +00:00
switch_media_bug_t * bp , * dp , * last = NULL ;
2007-06-13 03:09:53 +00:00
switch_bool_t ok = SWITCH_TRUE ;
2007-03-29 22:34:40 +00:00
switch_thread_rwlock_rdlock ( session - > bug_rwlock ) ;
for ( bp = session - > bugs ; bp ; bp = bp - > next ) {
if ( bp - > ready & & switch_test_flag ( bp , SMBF_READ_STREAM ) ) {
switch_mutex_lock ( bp - > read_mutex ) ;
switch_buffer_write ( bp - > raw_read_buffer , read_frame - > data , read_frame - > datalen ) ;
if ( bp - > callback ) {
2008-11-19 01:24:37 +00:00
ok = bp - > callback ( bp , bp - > user_data , SWITCH_ABC_TYPE_READ ) ;
2007-03-29 22:34:40 +00:00
}
switch_mutex_unlock ( bp - > read_mutex ) ;
2008-05-27 04:30:03 +00:00
}
2008-11-19 01:24:37 +00:00
if ( ok & & switch_test_flag ( bp , SMBF_READ_REPLACE ) ) {
2007-06-13 03:09:53 +00:00
do_bugs = 0 ;
if ( bp - > callback ) {
bp - > read_replace_frame_in = read_frame ;
2007-06-15 01:47:48 +00:00
bp - > read_replace_frame_out = read_frame ;
2007-06-13 03:09:53 +00:00
if ( ( ok = bp - > callback ( bp , bp - > user_data , SWITCH_ABC_TYPE_READ_REPLACE ) ) = = SWITCH_TRUE ) {
read_frame = bp - > read_replace_frame_out ;
}
}
}
2008-11-19 01:24:37 +00:00
2009-01-25 21:23:07 +00:00
if ( bp - > stop_time & & bp - > stop_time < = switch_epoch_time_now ( NULL ) ) {
2008-11-19 01:24:37 +00:00
ok = SWITCH_FALSE ;
}
2007-06-13 03:09:53 +00:00
if ( ok = = SWITCH_FALSE ) {
bp - > ready = 0 ;
if ( last ) {
last - > next = bp - > next ;
} else {
session - > bugs = bp - > next ;
}
dp = bp ;
bp = last ;
switch_core_media_bug_close ( & dp ) ;
if ( ! bp ) {
break ;
}
continue ;
2007-03-29 22:34:40 +00:00
}
last = bp ;
}
switch_thread_rwlock_unlock ( session - > bug_rwlock ) ;
}
if ( do_bugs ) {
goto done ;
}
if ( session - > read_codec ) {
2008-05-27 04:30:03 +00:00
if ( session - > read_resampler ) {
short * data = read_frame - > data ;
switch_mutex_lock ( session - > resample_mutex ) ;
2009-02-13 23:35:17 +00:00
switch_resample_process ( session - > read_resampler , data , ( int ) read_frame - > datalen / 2 ) ;
memcpy ( data , session - > read_resampler - > to , session - > read_resampler - > to_len * 2 ) ;
2008-05-27 04:30:03 +00:00
read_frame - > samples = session - > read_resampler - > to_len ;
2009-02-13 23:35:17 +00:00
read_frame - > datalen = session - > read_resampler - > to_len * 2 ;
read_frame - > rate = session - > read_resampler - > to_rate ;
2008-05-27 04:30:03 +00:00
switch_mutex_unlock ( session - > resample_mutex ) ;
}
2008-02-02 01:46:11 +00:00
2009-01-15 16:54:13 +00:00
if ( read_frame - > datalen = = session - > read_impl . decoded_bytes_per_packet ) {
2007-03-29 22:34:40 +00:00
perfect = TRUE ;
} else {
if ( ! session - > raw_read_buffer ) {
2009-01-15 16:54:13 +00:00
switch_size_t bytes = session - > read_impl . decoded_bytes_per_packet ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Engaging Read Buffer at %u bytes vs %u \n " ,
2008-09-05 20:34:18 +00:00
( uint32_t ) bytes , ( uint32_t ) ( * frame ) - > datalen ) ;
2007-03-30 00:13:31 +00:00
switch_buffer_create_dynamic ( & session - > raw_read_buffer , bytes * SWITCH_BUFFER_BLOCK_FRAMES , bytes * SWITCH_BUFFER_START_FRAMES , 0 ) ;
2007-03-29 22:34:40 +00:00
}
2009-09-10 00:46:24 +00:00
2007-03-29 22:34:40 +00:00
if ( ! switch_buffer_write ( session - > raw_read_buffer , read_frame - > data , read_frame - > datalen ) ) {
status = SWITCH_STATUS_MEMERR ;
goto done ;
}
}
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
2009-01-15 16:54:13 +00:00
if ( perfect | | switch_buffer_inuse ( session - > raw_read_buffer ) > = session - > read_impl . decoded_bytes_per_packet ) {
2007-03-29 22:34:40 +00:00
if ( perfect ) {
2008-09-08 21:52:52 +00:00
enc_frame = read_frame ;
session - > raw_read_frame . rate = read_frame - > rate ;
2007-03-29 22:34:40 +00:00
} else {
session - > raw_read_frame . datalen = ( uint32_t ) switch_buffer_read ( session - > raw_read_buffer ,
session - > raw_read_frame . data ,
2009-01-15 16:54:13 +00:00
session - > read_impl . decoded_bytes_per_packet ) ;
2007-03-29 22:34:40 +00:00
2009-01-15 16:54:13 +00:00
session - > raw_read_frame . rate = session - > read_impl . actual_samples_per_second ;
2007-03-29 22:34:40 +00:00
enc_frame = & session - > raw_read_frame ;
}
session - > enc_read_frame . datalen = session - > enc_read_frame . buflen ;
2007-06-13 21:51:18 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( session - > read_codec ! = NULL ) ;
switch_assert ( enc_frame ! = NULL ) ;
switch_assert ( enc_frame - > data ! = NULL ) ;
2007-03-29 22:34:40 +00:00
status = switch_core_codec_encode ( session - > read_codec ,
enc_frame - > codec ,
enc_frame - > data ,
enc_frame - > datalen ,
2009-01-15 16:54:13 +00:00
session - > read_impl . actual_samples_per_second ,
2007-03-30 00:13:31 +00:00
session - > enc_read_frame . data , & session - > enc_read_frame . datalen , & session - > enc_read_frame . rate , & flag ) ;
2007-03-29 22:34:40 +00:00
switch ( status ) {
case SWITCH_STATUS_RESAMPLE :
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Fixme 1 \n " ) ;
2007-03-29 22:34:40 +00:00
case SWITCH_STATUS_SUCCESS :
2009-01-15 16:54:13 +00:00
session - > enc_read_frame . samples = session - > read_impl . decoded_bytes_per_packet / sizeof ( int16_t ) ;
2008-03-28 15:27:17 +00:00
if ( perfect ) {
2009-01-15 16:54:13 +00:00
if ( enc_frame - > codec - > implementation - > samples_per_packet ! = session - > read_impl . samples_per_packet ) {
2008-11-12 10:28:16 +00:00
session - > enc_read_frame . timestamp = 0 ;
} else {
session - > enc_read_frame . timestamp = read_frame - > timestamp ;
}
2008-03-28 15:27:17 +00:00
session - > enc_read_frame . rate = read_frame - > rate ;
session - > enc_read_frame . ssrc = read_frame - > ssrc ;
session - > enc_read_frame . seq = read_frame - > seq ;
session - > enc_read_frame . m = read_frame - > m ;
2009-01-15 16:54:13 +00:00
session - > enc_read_frame . payload = session - > read_impl . ianacode ;
2008-03-28 15:27:17 +00:00
}
2007-03-29 22:34:40 +00:00
* frame = & session - > enc_read_frame ;
break ;
case SWITCH_STATUS_NOOP :
2008-10-20 17:48:42 +00:00
session - > raw_read_frame . samples = enc_frame - > codec - > implementation - > samples_per_packet ;
2007-03-29 22:34:40 +00:00
session - > raw_read_frame . timestamp = read_frame - > timestamp ;
session - > raw_read_frame . payload = enc_frame - > codec - > implementation - > ianacode ;
2007-04-19 21:40:50 +00:00
session - > raw_read_frame . m = read_frame - > m ;
session - > raw_read_frame . ssrc = read_frame - > ssrc ;
session - > raw_read_frame . seq = read_frame - > seq ;
2009-09-03 17:55:21 +00:00
* frame = enc_frame ;
2007-03-29 22:34:40 +00:00
status = SWITCH_STATUS_SUCCESS ;
break ;
2008-10-29 00:04:20 +00:00
case SWITCH_STATUS_NOT_INITALIZED :
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Codec init error! \n " ) ;
2008-10-29 00:04:20 +00:00
* frame = NULL ;
status = SWITCH_STATUS_GENERR ;
break ;
2007-03-29 22:34:40 +00:00
default :
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Codec %s encoder error! \n " ,
2007-03-30 00:15:25 +00:00
session - > read_codec - > codec_interface - > interface_name ) ;
2007-03-29 22:34:40 +00:00
* frame = NULL ;
status = SWITCH_STATUS_GENERR ;
break ;
}
} else {
goto top ;
}
}
}
done :
if ( ! ( * frame ) ) {
status = SWITCH_STATUS_FALSE ;
} else {
if ( flag & SFF_CNG ) {
switch_set_flag ( ( * frame ) , SFF_CNG ) ;
}
2009-01-26 16:47:00 +00:00
if ( session - > bugs & & ! switch_channel_test_flag ( session - > channel , CF_PAUSE_BUGS ) ) {
2007-12-06 22:26:37 +00:00
switch_media_bug_t * bp , * dp , * last = NULL ;
switch_bool_t ok = SWITCH_TRUE ;
switch_thread_rwlock_rdlock ( session - > bug_rwlock ) ;
for ( bp = session - > bugs ; bp ; bp = bp - > next ) {
if ( bp - > ready & & switch_test_flag ( bp , SMBF_READ_PING ) ) {
switch_mutex_lock ( bp - > read_mutex ) ;
if ( bp - > callback ) {
2008-05-27 04:30:03 +00:00
if ( bp - > callback ( bp , bp - > user_data , SWITCH_ABC_TYPE_READ_PING ) = = SWITCH_FALSE
2009-01-25 21:23:07 +00:00
| | ( bp - > stop_time & & bp - > stop_time < = switch_epoch_time_now ( NULL ) ) ) {
2007-12-06 22:26:37 +00:00
ok = SWITCH_FALSE ;
}
}
switch_mutex_unlock ( bp - > read_mutex ) ;
}
if ( ok = = SWITCH_FALSE ) {
bp - > ready = 0 ;
if ( last ) {
last - > next = bp - > next ;
} else {
session - > bugs = bp - > next ;
}
dp = bp ;
bp = last ;
switch_core_media_bug_close ( & dp ) ;
if ( ! bp ) {
break ;
}
continue ;
}
last = bp ;
}
switch_thread_rwlock_unlock ( session - > bug_rwlock ) ;
}
2007-03-29 22:34:40 +00:00
}
2008-05-01 16:41:46 +00:00
2008-05-27 04:30:03 +00:00
even_more_done :
2008-05-01 16:41:46 +00:00
2009-04-09 17:17:12 +00:00
if ( ! * frame | | ! ( * frame ) - > codec | | ! ( * frame ) - > codec - > implementation | | ! switch_core_codec_ready ( ( * frame ) - > codec ) ) {
2008-05-06 21:05:38 +00:00
* frame = & runtime . dummy_cng_frame ;
}
2008-11-19 20:12:20 +00:00
switch_mutex_unlock ( session - > read_codec - > mutex ) ;
2008-11-21 00:09:11 +00:00
switch_mutex_unlock ( session - > codec_read_mutex ) ;
2007-03-29 22:34:40 +00:00
return status ;
}
2008-05-08 19:19:47 +00:00
static switch_status_t perform_write ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id )
2007-03-29 22:34:40 +00:00
{
switch_io_event_hook_write_frame_t * ptr ;
switch_status_t status = SWITCH_STATUS_FALSE ;
if ( session - > endpoint_interface - > io_routines - > write_frame ) {
2008-05-08 19:19:47 +00:00
if ( ( status = session - > endpoint_interface - > io_routines - > write_frame ( session , frame , flags , stream_id ) ) = = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
for ( ptr = session - > event_hooks . write_frame ; ptr ; ptr = ptr - > next ) {
2008-05-08 19:19:47 +00:00
if ( ( status = ptr - > write_frame ( session , frame , flags , stream_id ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
break ;
}
}
}
}
2008-03-24 20:58:44 +00:00
2007-03-29 22:34:40 +00:00
return status ;
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_core_session_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags ,
int stream_id )
2007-03-29 22:34:40 +00:00
{
switch_status_t status = SWITCH_STATUS_FALSE ;
switch_frame_t * enc_frame = NULL , * write_frame = frame ;
2008-12-31 01:08:51 +00:00
unsigned int flag = 0 , need_codec = 0 , perfect = 0 , do_bugs = 0 , do_write = 0 , do_resample = 0 , ptime_mismatch = 0 , pass_cng = 0 , resample = 0 ;
2009-02-10 00:58:54 +00:00
int did_write_resample = 0 ;
2007-12-11 19:23:57 +00:00
switch_assert ( session ! = NULL ) ;
switch_assert ( frame ! = NULL ) ;
2007-03-29 22:34:40 +00:00
2009-01-14 20:46:02 +00:00
if ( ! switch_channel_ready ( session - > channel ) ) {
2008-03-10 19:04:01 +00:00
return SWITCH_STATUS_FALSE ;
}
2007-03-29 22:34:40 +00:00
2008-10-03 18:24:26 +00:00
if ( switch_test_flag ( frame , SFF_CNG ) ) {
if ( switch_channel_test_flag ( session - > channel , CF_ACCEPT_CNG ) ) {
pass_cng = 1 ;
}
return SWITCH_STATUS_SUCCESS ;
}
2009-04-09 17:17:12 +00:00
if ( ! ( session - > write_codec & & switch_core_codec_ready ( session - > write_codec ) ) & & ! pass_cng ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " %s has no write codec. \n " , switch_channel_get_name ( session - > channel ) ) ;
2008-05-08 20:54:37 +00:00
return SWITCH_STATUS_FALSE ;
}
2007-03-29 22:34:40 +00:00
if ( switch_channel_test_flag ( session - > channel , CF_HOLD ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2008-10-03 18:24:26 +00:00
if ( switch_test_flag ( frame , SFF_PROXY_PACKET ) | | pass_cng ) {
2008-02-21 17:48:41 +00:00
/* Fast PASS! */
2008-12-17 22:13:24 +00:00
switch_mutex_lock ( session - > codec_write_mutex ) ;
status = perform_write ( session , frame , flag , stream_id ) ;
switch_mutex_unlock ( session - > codec_write_mutex ) ;
return status ;
2008-02-21 17:48:41 +00:00
}
2007-12-11 19:23:57 +00:00
switch_assert ( frame - > codec ! = NULL ) ;
2008-10-17 23:00:23 +00:00
switch_assert ( frame - > codec - > implementation ! = NULL ) ;
2007-03-29 22:34:40 +00:00
2008-12-15 16:10:20 +00:00
switch_mutex_lock ( session - > codec_write_mutex ) ;
2009-01-14 20:46:02 +00:00
if ( ! ( session - > write_codec & & session - > write_codec - > mutex & & frame - > codec ) | |
! switch_channel_ready ( session - > channel ) | | ! switch_channel_media_ready ( session - > channel ) ) {
2008-12-15 16:10:20 +00:00
switch_mutex_unlock ( session - > codec_write_mutex ) ;
2008-11-19 20:12:20 +00:00
return SWITCH_STATUS_FALSE ;
}
2008-12-15 16:10:20 +00:00
2008-11-19 20:12:20 +00:00
switch_mutex_lock ( session - > write_codec - > mutex ) ;
2009-04-08 18:43:10 +00:00
switch_mutex_lock ( frame - > codec - > mutex ) ;
2009-01-14 20:46:02 +00:00
2007-03-29 22:34:40 +00:00
if ( ( session - > write_codec & & frame - > codec & & session - > write_codec - > implementation ! = frame - > codec - > implementation ) ) {
2009-01-24 00:39:37 +00:00
if ( session - > write_impl . codec_id = = frame - > codec - > implementation - > codec_id | |
session - > write_impl . microseconds_per_packet ! = frame - > codec - > implementation - > microseconds_per_packet ) {
2008-03-27 22:22:46 +00:00
ptime_mismatch = TRUE ;
2008-12-03 19:25:49 +00:00
if ( switch_test_flag ( frame - > codec , SWITCH_CODEC_FLAG_PASSTHROUGH ) | | switch_test_flag ( session - > read_codec , SWITCH_CODEC_FLAG_PASSTHROUGH ) ) {
2008-12-02 21:33:01 +00:00
status = perform_write ( session , frame , flags , stream_id ) ;
goto error ;
}
2008-03-27 22:22:46 +00:00
}
2008-12-02 21:33:01 +00:00
need_codec = TRUE ;
2007-03-29 22:34:40 +00:00
}
if ( session - > write_codec & & ! frame - > codec ) {
need_codec = TRUE ;
}
if ( session - > bugs & & ! need_codec ) {
2008-03-27 22:22:46 +00:00
do_bugs = TRUE ;
need_codec = TRUE ;
2007-03-29 22:34:40 +00:00
}
2009-01-15 16:54:13 +00:00
if ( frame - > codec - > implementation - > actual_samples_per_second ! = session - > write_impl . actual_samples_per_second ) {
2008-03-27 22:22:46 +00:00
need_codec = TRUE ;
do_resample = TRUE ;
2007-07-02 20:17:10 +00:00
}
2008-12-18 23:07:32 +00:00
if ( ! need_codec ) {
do_write = TRUE ;
2008-12-30 23:31:50 +00:00
write_frame = frame ;
2008-12-18 23:07:32 +00:00
goto done ;
}
if ( ! switch_test_flag ( session , SSF_WARN_TRANSCODE ) ) {
2008-05-13 20:36:23 +00:00
switch_core_session_message_t msg = { 0 } ;
2008-05-27 04:30:03 +00:00
2008-05-13 20:36:23 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY ;
switch_core_session_receive_message ( session , & msg ) ;
switch_set_flag ( session , SSF_WARN_TRANSCODE ) ;
2008-12-18 23:07:32 +00:00
}
2008-05-13 20:36:23 +00:00
2008-12-18 23:07:32 +00:00
if ( frame - > codec ) {
session - > raw_write_frame . datalen = session - > raw_write_frame . buflen ;
status = switch_core_codec_decode ( frame - > codec ,
session - > write_codec ,
frame - > data ,
frame - > datalen ,
2009-01-15 16:54:13 +00:00
session - > write_impl . actual_samples_per_second ,
2008-12-18 23:07:32 +00:00
session - > raw_write_frame . data , & session - > raw_write_frame . datalen , & session - > raw_write_frame . rate , & flag ) ;
2009-04-08 18:43:10 +00:00
2009-02-10 00:58:54 +00:00
2007-07-02 20:17:10 +00:00
2008-12-18 23:07:32 +00:00
if ( do_resample & & status = = SWITCH_STATUS_SUCCESS ) {
status = SWITCH_STATUS_RESAMPLE ;
}
2007-07-02 20:17:10 +00:00
2008-12-18 23:07:32 +00:00
switch ( status ) {
case SWITCH_STATUS_RESAMPLE :
2008-12-31 01:08:51 +00:00
resample + + ;
2008-12-18 23:07:32 +00:00
write_frame = & session - > raw_write_frame ;
2009-02-10 00:58:54 +00:00
write_frame - > rate = frame - > codec - > implementation - > actual_samples_per_second ;
2008-12-18 23:07:32 +00:00
if ( ! session - > write_resampler ) {
switch_mutex_lock ( session - > resample_mutex ) ;
status = switch_resample_create ( & session - > write_resampler ,
frame - > codec - > implementation - > actual_samples_per_second ,
2009-02-13 23:35:17 +00:00
session - > write_impl . actual_samples_per_second ,
session - > write_impl . decoded_bytes_per_packet ,
2009-07-23 15:55:13 +00:00
SWITCH_RESAMPLE_QUALITY , 1 ) ;
2009-02-13 23:35:17 +00:00
2009-04-08 18:43:10 +00:00
2008-12-18 23:07:32 +00:00
switch_mutex_unlock ( session - > resample_mutex ) ;
if ( status ! = SWITCH_STATUS_SUCCESS ) {
goto done ;
2008-05-31 16:48:54 +00:00
}
2008-12-18 23:07:32 +00:00
}
break ;
case SWITCH_STATUS_SUCCESS :
session - > raw_write_frame . samples = session - > raw_write_frame . datalen / sizeof ( int16_t ) ;
session - > raw_write_frame . timestamp = frame - > timestamp ;
session - > raw_write_frame . rate = frame - > rate ;
session - > raw_write_frame . m = frame - > m ;
session - > raw_write_frame . ssrc = frame - > ssrc ;
session - > raw_write_frame . seq = frame - > seq ;
session - > raw_write_frame . payload = frame - > payload ;
write_frame = & session - > raw_write_frame ;
break ;
case SWITCH_STATUS_BREAK :
status = SWITCH_STATUS_SUCCESS ; goto error ;
case SWITCH_STATUS_NOOP :
if ( session - > write_resampler ) {
switch_mutex_lock ( session - > resample_mutex ) ;
switch_resample_destroy ( & session - > write_resampler ) ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_NOTICE , " Deactivating write resampler \n " ) ;
2008-12-18 23:07:32 +00:00
switch_mutex_unlock ( session - > resample_mutex ) ;
}
write_frame = frame ;
status = SWITCH_STATUS_SUCCESS ;
break ;
default :
if ( status = = SWITCH_STATUS_NOT_INITALIZED ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Codec init error! \n " ) ;
2008-11-19 20:12:20 +00:00
goto error ;
2007-03-29 22:34:40 +00:00
}
2008-12-18 23:07:32 +00:00
if ( ptime_mismatch ) {
status = perform_write ( session , frame , flags , stream_id ) ;
status = SWITCH_STATUS_SUCCESS ; goto error ;
}
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Codec %s decoder error! \n " , frame - > codec - > codec_interface - > interface_name ) ;
2008-12-18 23:07:32 +00:00
goto error ;
2007-03-29 22:34:40 +00:00
}
2008-12-18 23:07:32 +00:00
}
2007-11-30 22:56:01 +00:00
2009-04-08 18:43:10 +00:00
2008-12-18 23:07:32 +00:00
if ( session - > write_resampler ) {
short * data = write_frame - > data ;
2008-05-27 04:30:03 +00:00
2008-12-18 23:07:32 +00:00
switch_mutex_lock ( session - > resample_mutex ) ;
2009-04-08 18:43:10 +00:00
if ( session - > write_resampler ) {
switch_resample_process ( session - > write_resampler , data , write_frame - > datalen / 2 ) ;
memcpy ( data , session - > write_resampler - > to , session - > write_resampler - > to_len * 2 ) ;
write_frame - > samples = session - > write_resampler - > to_len ;
write_frame - > datalen = write_frame - > samples * 2 ;
write_frame - > rate = session - > write_resampler - > to_rate ;
did_write_resample = 1 ;
}
2008-12-18 23:07:32 +00:00
switch_mutex_unlock ( session - > resample_mutex ) ;
}
2007-03-29 22:34:40 +00:00
2009-04-08 18:43:10 +00:00
2009-01-26 16:47:00 +00:00
if ( session - > bugs & & ! switch_channel_test_flag ( session - > channel , CF_PAUSE_BUGS ) ) {
2008-12-18 23:07:32 +00:00
switch_media_bug_t * bp , * dp , * last = NULL ;
2009-02-10 00:58:54 +00:00
2008-12-18 23:07:32 +00:00
switch_thread_rwlock_rdlock ( session - > bug_rwlock ) ;
for ( bp = session - > bugs ; bp ; bp = bp - > next ) {
switch_bool_t ok = SWITCH_TRUE ;
if ( ! bp - > ready ) {
continue ;
}
if ( switch_test_flag ( bp , SMBF_WRITE_STREAM ) ) {
2008-05-27 04:30:03 +00:00
2008-12-18 23:07:32 +00:00
switch_mutex_lock ( bp - > write_mutex ) ;
switch_buffer_write ( bp - > raw_write_buffer , write_frame - > data , write_frame - > datalen ) ;
switch_mutex_unlock ( bp - > write_mutex ) ;
if ( bp - > callback ) {
ok = bp - > callback ( bp , bp - > user_data , SWITCH_ABC_TYPE_WRITE ) ;
2008-05-27 04:30:03 +00:00
}
2008-12-18 23:07:32 +00:00
}
2007-11-30 22:56:01 +00:00
2008-12-18 23:07:32 +00:00
if ( switch_test_flag ( bp , SMBF_WRITE_REPLACE ) ) {
do_bugs = 0 ;
if ( bp - > callback ) {
bp - > write_replace_frame_in = write_frame ;
bp - > write_replace_frame_out = write_frame ;
if ( ( ok = bp - > callback ( bp , bp - > user_data , SWITCH_ABC_TYPE_WRITE_REPLACE ) ) = = SWITCH_TRUE ) {
write_frame = bp - > write_replace_frame_out ;
2007-03-29 22:34:40 +00:00
}
}
2008-12-18 23:07:32 +00:00
}
2007-03-29 22:34:40 +00:00
2009-01-25 21:23:07 +00:00
if ( bp - > stop_time & & bp - > stop_time < = switch_epoch_time_now ( NULL ) ) {
2008-12-18 23:07:32 +00:00
ok = SWITCH_FALSE ;
}
2007-05-31 14:42:23 +00:00
2008-12-18 23:07:32 +00:00
if ( ok = = SWITCH_FALSE ) {
bp - > ready = 0 ;
if ( last ) {
last - > next = bp - > next ;
} else {
session - > bugs = bp - > next ;
2007-03-29 22:34:40 +00:00
}
2008-12-18 23:07:32 +00:00
dp = bp ;
bp = last ;
switch_core_media_bug_close ( & dp ) ;
if ( ! bp ) {
break ;
}
continue ;
2007-03-29 22:34:40 +00:00
}
2008-12-18 23:07:32 +00:00
last = bp ;
2007-03-29 22:34:40 +00:00
}
2008-12-18 23:07:32 +00:00
switch_thread_rwlock_unlock ( session - > bug_rwlock ) ;
}
2007-03-29 22:34:40 +00:00
2008-12-18 23:07:32 +00:00
if ( do_bugs ) {
do_write = TRUE ;
write_frame = frame ;
goto done ;
}
2007-12-07 01:57:30 +00:00
2008-12-18 23:07:32 +00:00
if ( session - > write_codec ) {
2009-02-16 18:56:13 +00:00
if ( ! ptime_mismatch & & write_frame - > codec & & write_frame - > codec - > implementation & &
2009-01-15 16:54:13 +00:00
write_frame - > codec - > implementation - > decoded_bytes_per_packet = = session - > write_impl . decoded_bytes_per_packet ) {
2008-12-18 23:07:32 +00:00
perfect = TRUE ;
}
2009-04-08 18:43:10 +00:00
2009-01-15 16:54:13 +00:00
2009-04-08 18:43:10 +00:00
2008-12-18 23:07:32 +00:00
if ( perfect ) {
2009-02-10 00:58:54 +00:00
2009-01-15 16:54:13 +00:00
if ( write_frame - > datalen < session - > write_impl . decoded_bytes_per_packet ) {
memset ( write_frame - > data , 255 , session - > write_impl . decoded_bytes_per_packet - write_frame - > datalen ) ;
write_frame - > datalen = session - > write_impl . decoded_bytes_per_packet ;
2009-01-09 20:34:01 +00:00
}
2008-12-18 23:07:32 +00:00
enc_frame = write_frame ;
session - > enc_write_frame . datalen = session - > enc_write_frame . buflen ;
2007-03-29 22:34:40 +00:00
2008-12-18 23:07:32 +00:00
status = switch_core_codec_encode ( session - > write_codec ,
frame - > codec ,
enc_frame - > data ,
enc_frame - > datalen ,
2009-01-15 16:54:13 +00:00
session - > write_impl . actual_samples_per_second ,
2008-12-18 23:07:32 +00:00
session - > enc_write_frame . data , & session - > enc_write_frame . datalen , & session - > enc_write_frame . rate , & flag ) ;
2007-03-29 22:34:40 +00:00
2009-04-08 18:43:10 +00:00
2008-12-18 23:07:32 +00:00
switch ( status ) {
case SWITCH_STATUS_RESAMPLE :
2008-12-31 01:08:51 +00:00
resample + + ;
2009-08-13 20:35:02 +00:00
/* switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 2\n"); */
2008-12-18 23:07:32 +00:00
case SWITCH_STATUS_SUCCESS :
session - > enc_write_frame . codec = session - > write_codec ;
session - > enc_write_frame . samples = enc_frame - > datalen / sizeof ( int16_t ) ;
2009-01-15 16:54:13 +00:00
if ( frame - > codec - > implementation - > samples_per_packet ! = session - > write_impl . samples_per_packet ) {
2008-12-18 23:07:32 +00:00
session - > enc_write_frame . timestamp = 0 ;
} else {
session - > enc_write_frame . timestamp = frame - > timestamp ;
2007-03-29 22:34:40 +00:00
}
2009-01-15 16:54:13 +00:00
session - > enc_write_frame . payload = session - > write_impl . ianacode ;
2008-12-18 23:07:32 +00:00
session - > enc_write_frame . m = frame - > m ;
session - > enc_write_frame . ssrc = frame - > ssrc ;
session - > enc_write_frame . seq = frame - > seq ;
write_frame = & session - > enc_write_frame ;
break ;
case SWITCH_STATUS_NOOP :
enc_frame - > codec = session - > write_codec ;
enc_frame - > samples = enc_frame - > datalen / sizeof ( int16_t ) ;
enc_frame - > timestamp = frame - > timestamp ;
enc_frame - > m = frame - > m ;
enc_frame - > seq = frame - > seq ;
enc_frame - > ssrc = frame - > ssrc ;
enc_frame - > payload = enc_frame - > codec - > implementation - > ianacode ;
write_frame = enc_frame ;
status = SWITCH_STATUS_SUCCESS ;
break ;
case SWITCH_STATUS_NOT_INITALIZED :
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Codec init error! \n " ) ;
2008-12-18 23:07:32 +00:00
write_frame = NULL ;
goto error ;
default :
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Codec %s encoder error! \n " ,
2008-12-18 23:07:32 +00:00
session - > read_codec - > codec_interface - > interface_name ) ;
write_frame = NULL ;
goto error ;
}
if ( flag & SFF_CNG ) {
switch_set_flag ( write_frame , SFF_CNG ) ;
}
2009-04-08 18:43:10 +00:00
2008-12-18 23:07:32 +00:00
status = perform_write ( session , write_frame , flags , stream_id ) ;
goto error ;
} else {
2009-01-15 16:54:13 +00:00
if ( ! session - > raw_write_buffer ) {
switch_size_t bytes_per_packet = session - > write_impl . decoded_bytes_per_packet ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG ,
2009-01-15 16:54:13 +00:00
" Engaging Write Buffer at %u bytes to accommodate %u->%u \n " ,
( uint32_t ) bytes_per_packet , write_frame - > datalen , session - > write_impl . decoded_bytes_per_packet ) ;
if ( ( status = switch_buffer_create_dynamic ( & session - > raw_write_buffer ,
bytes_per_packet * SWITCH_BUFFER_BLOCK_FRAMES ,
bytes_per_packet * SWITCH_BUFFER_START_FRAMES , 0 ) ) ! = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Write Buffer Failed! \n " ) ;
2009-01-15 16:54:13 +00:00
goto error ;
}
}
2009-02-10 00:58:54 +00:00
2009-01-15 16:54:13 +00:00
if ( ! ( switch_buffer_write ( session - > raw_write_buffer , write_frame - > data , write_frame - > datalen ) ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Write Buffer %u bytes Failed! \n " , write_frame - > datalen ) ;
2009-01-15 16:54:13 +00:00
status = SWITCH_STATUS_MEMERR ; goto error ;
}
2008-12-18 23:07:32 +00:00
status = SWITCH_STATUS_SUCCESS ;
2009-02-10 00:58:54 +00:00
2009-09-10 00:46:24 +00:00
while ( switch_buffer_inuse ( session - > raw_write_buffer ) > = session - > write_impl . decoded_bytes_per_packet ) {
int rate ;
if ( switch_channel_down ( session - > channel ) | | ! session - > raw_write_buffer ) {
goto error ;
}
if ( ( session - > raw_write_frame . datalen = ( uint32_t )
switch_buffer_read ( session - > raw_write_buffer , session - > raw_write_frame . data , session - > write_impl . decoded_bytes_per_packet ) ) = = 0 ) {
goto error ;
}
enc_frame = & session - > raw_write_frame ;
session - > raw_write_frame . rate = session - > write_impl . actual_samples_per_second ;
session - > enc_write_frame . datalen = session - > enc_write_frame . buflen ;
session - > enc_write_frame . timestamp = 0 ;
if ( frame - > codec & & frame - > codec - > implementation & & switch_core_codec_ready ( frame - > codec ) ) {
rate = frame - > codec - > implementation - > actual_samples_per_second ;
} else {
rate = session - > write_impl . actual_samples_per_second ;
}
2009-02-10 00:58:54 +00:00
2009-09-10 00:46:24 +00:00
status = switch_core_codec_encode ( session - > write_codec ,
frame - > codec ,
enc_frame - > data ,
enc_frame - > datalen ,
rate ,
session - > enc_write_frame . data ,
& session - > enc_write_frame . datalen ,
& session - > enc_write_frame . rate , & flag ) ;
2009-04-08 18:43:10 +00:00
2009-09-10 00:46:24 +00:00
switch ( status ) {
case SWITCH_STATUS_RESAMPLE :
resample + + ;
session - > enc_write_frame . codec = session - > write_codec ;
session - > enc_write_frame . samples = enc_frame - > datalen / sizeof ( int16_t ) ;
session - > enc_write_frame . m = frame - > m ;
session - > enc_write_frame . ssrc = frame - > ssrc ;
session - > enc_write_frame . payload = session - > write_impl . ianacode ;
write_frame = & session - > enc_write_frame ;
if ( ! session - > write_resampler ) {
switch_mutex_lock ( session - > resample_mutex ) ;
if ( ! session - > write_resampler ) {
status = switch_resample_create ( & session - > write_resampler ,
frame - > codec - > implementation - > actual_samples_per_second ,
session - > write_impl . actual_samples_per_second ,
session - > write_impl . decoded_bytes_per_packet ,
SWITCH_RESAMPLE_QUALITY , 1 ) ;
}
switch_mutex_unlock ( session - > resample_mutex ) ;
2008-05-27 04:30:03 +00:00
2009-04-08 18:43:10 +00:00
2009-09-10 00:46:24 +00:00
if ( status ! = SWITCH_STATUS_SUCCESS ) {
goto done ;
}
}
break ;
case SWITCH_STATUS_SUCCESS :
session - > enc_write_frame . codec = session - > write_codec ;
session - > enc_write_frame . samples = enc_frame - > datalen / sizeof ( int16_t ) ;
session - > enc_write_frame . m = frame - > m ;
session - > enc_write_frame . ssrc = frame - > ssrc ;
session - > enc_write_frame . payload = session - > write_impl . ianacode ;
write_frame = & session - > enc_write_frame ;
break ;
case SWITCH_STATUS_NOOP :
if ( session - > write_resampler ) {
switch_mutex_lock ( session - > resample_mutex ) ;
if ( session - > write_resampler ) {
switch_resample_destroy ( & session - > write_resampler ) ;
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_NOTICE , " Deactivating write resampler \n " ) ;
2008-12-18 23:07:32 +00:00
}
2009-09-10 00:46:24 +00:00
switch_mutex_unlock ( session - > resample_mutex ) ;
}
enc_frame - > codec = session - > write_codec ;
enc_frame - > samples = enc_frame - > datalen / sizeof ( int16_t ) ;
enc_frame - > m = frame - > m ;
enc_frame - > ssrc = frame - > ssrc ;
enc_frame - > payload = enc_frame - > codec - > implementation - > ianacode ;
write_frame = enc_frame ;
status = SWITCH_STATUS_SUCCESS ;
break ;
case SWITCH_STATUS_NOT_INITALIZED :
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Codec init error! \n " ) ;
write_frame = NULL ;
goto error ;
default :
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Codec %s encoder error %d! \n " ,
session - > read_codec - > codec_interface - > interface_name , status ) ;
write_frame = NULL ;
goto error ;
}
2008-03-27 22:22:46 +00:00
2009-09-10 00:46:24 +00:00
if ( ! did_write_resample & & session - > read_resampler ) {
short * data = write_frame - > data ;
switch_mutex_lock ( session - > resample_mutex ) ;
if ( session - > read_resampler ) {
switch_resample_process ( session - > read_resampler , data , write_frame - > datalen / 2 ) ;
memcpy ( data , session - > read_resampler - > to , session - > read_resampler - > to_len * 2 ) ;
write_frame - > samples = session - > read_resampler - > to_len ;
write_frame - > datalen = session - > read_resampler - > to_len * 2 ;
write_frame - > rate = session - > read_resampler - > to_rate ;
}
switch_mutex_unlock ( session - > resample_mutex ) ;
2008-12-18 23:07:32 +00:00
2009-09-10 00:46:24 +00:00
}
2008-12-30 23:31:50 +00:00
2009-09-10 00:46:24 +00:00
if ( flag & SFF_CNG ) {
switch_set_flag ( write_frame , SFF_CNG ) ;
}
2008-12-30 23:31:50 +00:00
2009-09-10 00:46:24 +00:00
if ( ptime_mismatch | | resample ) {
write_frame - > timestamp = 0 ;
}
2008-12-18 23:07:32 +00:00
2009-09-10 00:46:24 +00:00
if ( ( status = perform_write ( session , write_frame , flags , stream_id ) ) ! = SWITCH_STATUS_SUCCESS ) {
break ;
2007-03-29 22:34:40 +00:00
}
2009-09-10 00:46:24 +00:00
2007-03-29 22:34:40 +00:00
}
2009-09-10 00:46:24 +00:00
goto error ;
2007-03-29 22:34:40 +00:00
}
}
2009-09-10 00:46:24 +00:00
2008-12-18 23:07:32 +00:00
2008-11-19 20:12:20 +00:00
done :
2008-03-24 20:58:44 +00:00
2008-12-31 01:08:51 +00:00
if ( ptime_mismatch | | resample ) {
2008-12-30 23:31:50 +00:00
write_frame - > timestamp = 0 ;
}
2007-03-29 22:34:40 +00:00
if ( do_write ) {
2009-09-10 00:46:24 +00:00
status = perform_write ( session , write_frame , flags , stream_id ) ;
2007-03-29 22:34:40 +00:00
}
2008-11-19 20:12:20 +00:00
error :
switch_mutex_unlock ( session - > write_codec - > mutex ) ;
2009-04-08 18:43:10 +00:00
switch_mutex_unlock ( frame - > codec - > mutex ) ;
2008-11-21 00:09:11 +00:00
switch_mutex_unlock ( session - > codec_write_mutex ) ;
2007-03-29 22:34:40 +00:00
return status ;
}
static char * SIG_NAMES [ ] = {
" NONE " ,
" KILL " ,
" XFER " ,
" BREAK " ,
NULL
} ;
SWITCH_DECLARE ( switch_status_t ) switch_core_session_perform_kill_channel ( switch_core_session_t * session ,
2007-03-30 00:13:31 +00:00
const char * file , const char * func , int line , switch_signal_t sig )
2007-03-29 22:34:40 +00:00
{
switch_io_event_hook_kill_channel_t * ptr ;
switch_status_t status = SWITCH_STATUS_FALSE ;
2009-08-13 21:24:51 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , switch_core_session_get_uuid ( session ) , SWITCH_LOG_DEBUG , " Send signal %s [%s] \n " , switch_channel_get_name ( session - > channel ) ,
2007-03-30 00:15:25 +00:00
SIG_NAMES [ sig ] ) ;
2007-03-29 22:34:40 +00:00
if ( session - > endpoint_interface - > io_routines - > kill_channel ) {
if ( ( status = session - > endpoint_interface - > io_routines - > kill_channel ( session , sig ) ) = = SWITCH_STATUS_SUCCESS ) {
for ( ptr = session - > event_hooks . kill_channel ; ptr ; ptr = ptr - > next ) {
if ( ( status = ptr - > kill_channel ( session , sig ) ) ! = SWITCH_STATUS_SUCCESS ) {
break ;
}
}
}
}
return status ;
}
2007-12-22 00:32:20 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_core_session_recv_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf )
2007-06-12 21:00:26 +00:00
{
2008-05-27 04:30:03 +00:00
switch_io_event_hook_recv_dtmf_t * ptr ;
2007-06-12 21:00:26 +00:00
switch_status_t status ;
2008-02-21 21:38:49 +00:00
switch_dtmf_t new_dtmf ;
2008-05-27 04:30:03 +00:00
2009-02-25 03:41:18 +00:00
if ( switch_channel_down ( session - > channel ) ) {
2008-03-10 19:04:01 +00:00
return SWITCH_STATUS_FALSE ;
}
2008-02-21 21:38:49 +00:00
switch_assert ( dtmf ) ;
new_dtmf = * dtmf ;
2008-04-18 17:03:34 +00:00
if ( new_dtmf . duration > switch_core_max_dtmf_duration ( 0 ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " %s EXCESSIVE DTMF DIGIT [%c] LEN [%d] \n " ,
2008-02-21 21:38:49 +00:00
switch_channel_get_name ( session - > channel ) , new_dtmf . digit , new_dtmf . duration ) ;
2008-04-18 17:03:34 +00:00
new_dtmf . duration = switch_core_max_dtmf_duration ( 0 ) ;
2009-09-16 21:24:22 +00:00
} else if ( new_dtmf . duration < switch_core_min_dtmf_duration ( 0 ) ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " %s SHORT DTMF DIGIT [%c] LEN [%d] \n " ,
switch_channel_get_name ( session - > channel ) , new_dtmf . digit , new_dtmf . duration ) ;
new_dtmf . duration = switch_core_min_dtmf_duration ( 0 ) ;
2008-02-21 21:38:49 +00:00
} else if ( ! new_dtmf . duration ) {
2008-04-18 17:03:34 +00:00
new_dtmf . duration = switch_core_default_dtmf_duration ( 0 ) ;
2008-02-21 21:38:49 +00:00
}
2007-06-12 21:00:26 +00:00
for ( ptr = session - > event_hooks . recv_dtmf ; ptr ; ptr = ptr - > next ) {
2008-05-19 21:02:26 +00:00
if ( ( status = ptr - > recv_dtmf ( session , & new_dtmf , SWITCH_DTMF_RECV ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-06-12 21:00:26 +00:00
return status ;
}
}
return SWITCH_STATUS_SUCCESS ;
}
2007-12-22 00:32:20 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_core_session_send_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf )
2007-03-29 22:34:40 +00:00
{
switch_io_event_hook_send_dtmf_t * ptr ;
switch_status_t status = SWITCH_STATUS_FALSE ;
2008-02-21 21:38:49 +00:00
switch_dtmf_t new_dtmf ;
2008-05-27 04:30:03 +00:00
2009-02-25 03:41:18 +00:00
if ( switch_channel_down ( session - > channel ) ) {
2008-03-10 19:04:01 +00:00
return SWITCH_STATUS_FALSE ;
}
2008-02-21 21:38:49 +00:00
switch_assert ( dtmf ) ;
new_dtmf = * dtmf ;
2008-04-18 17:03:34 +00:00
if ( new_dtmf . duration > switch_core_max_dtmf_duration ( 0 ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " %s EXCESSIVE DTMF DIGIT [%c] LEN [%d] \n " ,
2008-02-21 21:38:49 +00:00
switch_channel_get_name ( session - > channel ) , new_dtmf . digit , new_dtmf . duration ) ;
2008-04-18 17:03:34 +00:00
new_dtmf . duration = switch_core_max_dtmf_duration ( 0 ) ;
2009-09-16 21:24:22 +00:00
} else if ( new_dtmf . duration < switch_core_min_dtmf_duration ( 0 ) ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " %s SHORT DTMF DIGIT [%c] LEN [%d] \n " ,
switch_channel_get_name ( session - > channel ) , new_dtmf . digit , new_dtmf . duration ) ;
new_dtmf . duration = switch_core_min_dtmf_duration ( 0 ) ;
2008-02-21 21:38:49 +00:00
} else if ( ! new_dtmf . duration ) {
2008-04-18 17:03:34 +00:00
new_dtmf . duration = switch_core_default_dtmf_duration ( 0 ) ;
2008-02-21 21:38:49 +00:00
}
2007-06-12 21:00:26 +00:00
for ( ptr = session - > event_hooks . send_dtmf ; ptr ; ptr = ptr - > next ) {
2008-05-19 21:02:26 +00:00
if ( ( status = ptr - > send_dtmf ( session , dtmf , SWITCH_DTMF_SEND ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-06-12 21:00:26 +00:00
return SWITCH_STATUS_SUCCESS ;
}
}
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
if ( session - > endpoint_interface - > io_routines - > send_dtmf ) {
2007-12-22 00:32:20 +00:00
if ( dtmf - > digit = = ' w ' ) {
switch_yield ( 500000 ) ;
} else if ( dtmf - > digit = = ' W ' ) {
switch_yield ( 1000000 ) ;
2007-03-29 22:34:40 +00:00
} else {
2008-02-21 21:38:49 +00:00
status = session - > endpoint_interface - > io_routines - > send_dtmf ( session , & new_dtmf ) ;
2007-03-29 22:34:40 +00:00
}
}
return status ;
}
2008-01-12 20:30:48 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_core_session_send_dtmf_string ( switch_core_session_t * session , const char * dtmf_string )
{
char * p ;
2008-05-27 04:30:03 +00:00
switch_dtmf_t dtmf = { 0 , switch_core_default_dtmf_duration ( 0 ) } ;
2008-01-12 20:30:48 +00:00
int sent = 0 , dur ;
char * string ;
int i , argc ;
char * argv [ 256 ] ;
2008-09-11 17:29:08 +00:00
int dur_total = 0 ;
2008-05-27 04:30:03 +00:00
2008-01-12 20:30:48 +00:00
switch_assert ( session ! = NULL ) ;
2008-03-10 19:04:01 +00:00
2009-02-25 03:41:18 +00:00
if ( switch_channel_down ( session - > channel ) ) {
2008-03-10 19:04:01 +00:00
return SWITCH_STATUS_FALSE ;
}
2008-05-27 04:30:03 +00:00
2008-01-12 20:30:48 +00:00
if ( switch_strlen_zero ( dtmf_string ) ) {
return SWITCH_STATUS_FALSE ;
}
2008-01-14 21:27:40 +00:00
if ( strlen ( dtmf_string ) > 99 ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Attempt to send very large dtmf string ignored! \n " ) ;
2008-01-14 21:27:40 +00:00
return SWITCH_STATUS_FALSE ;
}
2008-01-12 20:30:48 +00:00
string = switch_core_session_strdup ( session , dtmf_string ) ;
argc = switch_separate_string ( string , ' + ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
2008-05-27 04:30:03 +00:00
2008-01-12 20:30:48 +00:00
if ( argc ) {
switch_channel_pre_answer ( session - > channel ) ;
}
2008-05-27 04:30:03 +00:00
for ( i = 0 ; i < argc ; i + + ) {
2008-04-18 17:03:34 +00:00
dtmf . duration = switch_core_default_dtmf_duration ( 0 ) ;
dur = switch_core_default_dtmf_duration ( 0 ) / 8 ;
2008-01-12 20:30:48 +00:00
if ( ( p = strchr ( argv [ i ] , ' @ ' ) ) ) {
* p + + = ' \0 ' ;
if ( ( dur = atoi ( p ) ) > 50 ) {
dtmf . duration = dur * 8 ;
}
}
2008-02-21 21:38:49 +00:00
2008-04-18 17:03:34 +00:00
if ( dtmf . duration > switch_core_max_dtmf_duration ( 0 ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " %s EXCESSIVE DTMF DIGIT [%c] LEN [%d] \n " ,
2008-02-21 21:38:49 +00:00
switch_channel_get_name ( session - > channel ) , dtmf . digit , dtmf . duration ) ;
2008-04-18 17:03:34 +00:00
dtmf . duration = switch_core_max_dtmf_duration ( 0 ) ;
2009-09-16 21:24:22 +00:00
} else if ( dtmf . duration < switch_core_min_dtmf_duration ( 0 ) ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " %s SHORT DTMF DIGIT [%c] LEN [%d] \n " ,
switch_channel_get_name ( session - > channel ) , dtmf . digit , dtmf . duration ) ;
dtmf . duration = switch_core_min_dtmf_duration ( 0 ) ;
2008-02-21 21:38:49 +00:00
} else if ( ! dtmf . duration ) {
2008-04-18 17:03:34 +00:00
dtmf . duration = switch_core_default_dtmf_duration ( 0 ) ;
2008-02-21 21:38:49 +00:00
}
2008-01-12 20:30:48 +00:00
for ( p = argv [ i ] ; p & & * p ; p + + ) {
if ( is_dtmf ( * p ) ) {
dtmf . digit = * p ;
if ( switch_core_session_send_dtmf ( session , & dtmf ) = = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s send dtmf \n digit=%c ms=%u samples=%u \n " ,
2008-01-12 20:30:48 +00:00
switch_channel_get_name ( session - > channel ) , dtmf . digit , dur , dtmf . duration ) ;
sent + + ;
2008-09-11 17:29:08 +00:00
dur_total + = dtmf . duration + 2000 ; /* account for 250ms pause */
2008-01-12 20:30:48 +00:00
}
}
}
2008-05-27 04:30:03 +00:00
2008-09-11 17:29:08 +00:00
if ( dur_total ) {
char tmp [ 32 ] = " " ;
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , dur_total / 8 ) ;
switch_channel_set_variable ( session - > channel , " last_dtmf_duration " , tmp ) ;
}
2008-01-12 20:30:48 +00:00
}
return sent ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE ;
}
2008-01-27 05:02:52 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2008-02-03 22:14:57 +00:00
* indent - tabs - mode : t
2008-01-27 05:02:52 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2008-07-03 19:12:26 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
2008-01-27 05:02:52 +00:00
*/