[commit] r4977 - in freeswitch/trunk/src: . include mod/codecs/mod_h26x mod/endpoints/mod_sofia
Author: anthm Date: Thu Apr 19 17:40:50 2007 New Revision: 4977 Added: freeswitch/trunk/src/mod/codecs/mod_h26x/ freeswitch/trunk/src/mod/codecs/mod_h26x/Makefile freeswitch/trunk/src/mod/codecs/mod_h26x/mod_h26x.c freeswitch/trunk/src/mod/codecs/mod_h26x/mod_h26x.vcproj Modified: freeswitch/trunk/src/include/switch_core.h freeswitch/trunk/src/include/switch_core_event_hook.h freeswitch/trunk/src/include/switch_frame.h freeswitch/trunk/src/include/switch_ivr.h freeswitch/trunk/src/include/switch_module_interfaces.h freeswitch/trunk/src/include/switch_types.h freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c freeswitch/trunk/src/switch_core_event_hook.c freeswitch/trunk/src/switch_core_io.c freeswitch/trunk/src/switch_core_state_machine.c freeswitch/trunk/src/switch_ivr_async.c freeswitch/trunk/src/switch_rtp.c Log: modest core framework for video stuff Modified: freeswitch/trunk/src/include/switch_core.h ============================================================================== --- freeswitch/trunk/src/include/switch_core.h (original) +++ freeswitch/trunk/src/include/switch_core.h Thu Apr 19 17:40:50 2007 @@ -714,6 +714,9 @@ */ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, int stream_id); +SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, int stream_id); +SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, int stream_id); + /*! \brief Reset the buffers and resampler on a session \param session the session to reset Modified: freeswitch/trunk/src/include/switch_core_event_hook.h ============================================================================== --- freeswitch/trunk/src/include/switch_core_event_hook.h (original) +++ freeswitch/trunk/src/include/switch_core_event_hook.h Thu Apr 19 17:40:50 2007 @@ -38,7 +38,9 @@ typedef struct switch_io_event_hook_receive_message switch_io_event_hook_receive_message_t; typedef struct switch_io_event_hook_receive_event switch_io_event_hook_receive_event_t; typedef struct switch_io_event_hook_read_frame switch_io_event_hook_read_frame_t; +typedef struct switch_io_event_hook_video_read_frame switch_io_event_hook_video_read_frame_t; typedef struct switch_io_event_hook_write_frame switch_io_event_hook_write_frame_t; +typedef struct switch_io_event_hook_video_write_frame switch_io_event_hook_video_write_frame_t; typedef struct switch_io_event_hook_kill_channel switch_io_event_hook_kill_channel_t; typedef struct switch_io_event_hook_waitfor_read switch_io_event_hook_waitfor_read_t; typedef struct switch_io_event_hook_waitfor_write switch_io_event_hook_waitfor_write_t; @@ -50,7 +52,9 @@ typedef switch_status_t (*switch_receive_message_hook_t) (switch_core_session_t *, switch_core_session_message_t *); typedef switch_status_t (*switch_receive_event_hook_t) (switch_core_session_t *, switch_event_t *); typedef switch_status_t (*switch_read_frame_hook_t) (switch_core_session_t *, switch_frame_t **, int, switch_io_flag_t, int); +typedef switch_status_t (*switch_video_read_frame_hook_t) (switch_core_session_t *, switch_frame_t **, int, switch_io_flag_t, int); typedef switch_status_t (*switch_write_frame_hook_t) (switch_core_session_t *, switch_frame_t *, int, switch_io_flag_t, int); +typedef switch_status_t (*switch_video_write_frame_hook_t) (switch_core_session_t *, switch_frame_t *, int, switch_io_flag_t, int); typedef switch_status_t (*switch_kill_channel_hook_t) (switch_core_session_t *, int); typedef switch_status_t (*switch_waitfor_read_hook_t) (switch_core_session_t *, int, int); typedef switch_status_t (*switch_waitfor_write_hook_t) (switch_core_session_t *, int, int); @@ -86,6 +90,13 @@ struct switch_io_event_hook_read_frame *next; }; +/*! \brief Node in which to store custom read frame channel callback hooks */ +struct switch_io_event_hook_video_read_frame { + /*! the read frame channel callback hook */ + switch_read_frame_hook_t video_read_frame; + struct switch_io_event_hook_video_read_frame *next; +}; + /*! \brief Node in which to store custom write_frame channel callback hooks */ struct switch_io_event_hook_write_frame { /*! the write_frame channel callback hook */ @@ -93,6 +104,13 @@ struct switch_io_event_hook_write_frame *next; }; +/*! \brief Node in which to store custom video_write_frame channel callback hooks */ +struct switch_io_event_hook_video_write_frame { + /*! the video_write_frame channel callback hook */ + switch_video_write_frame_hook_t video_write_frame; + struct switch_io_event_hook_video_write_frame *next; +}; + /*! \brief Node in which to store custom kill channel callback hooks */ struct switch_io_event_hook_kill_channel { /*! the kill channel callback hook */ @@ -138,8 +156,12 @@ switch_io_event_hook_receive_event_t *receive_event; /*! a list of read frame hooks */ switch_io_event_hook_read_frame_t *read_frame; + /*! a list of video read frame hooks */ + switch_io_event_hook_video_read_frame_t *video_read_frame; /*! a list of write frame hooks */ switch_io_event_hook_write_frame_t *write_frame; + /*! a list of video write frame hooks */ + switch_io_event_hook_video_write_frame_t *video_write_frame; /*! a list of kill channel hooks */ switch_io_event_hook_kill_channel_t *kill_channel; /*! a list of wait for read hooks */ @@ -186,6 +208,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_event_hook_add_read_frame(switch_core_session_t *session, switch_read_frame_hook_t read_frame); /*! + \brief Add an event hook to be executed when a session reads a frame + \param session session to bind hook to + \param video_read_frame hook to bind + \return SWITCH_STATUS_SUCCESS on suceess +*/ +SWITCH_DECLARE(switch_status_t) switch_core_event_hook_add_video_read_frame(switch_core_session_t *session, switch_read_frame_hook_t video_read_frame); + +/*! \brief Add an event hook to be executed when a session writes a frame \param session session to bind hook to \param write_frame hook to bind @@ -194,6 +224,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_event_hook_add_write_frame(switch_core_session_t *session, switch_write_frame_hook_t write_frame); /*! + \brief Add an event hook to be executed when a session writes a video frame + \param session session to bind hook to + \param write_frame hook to bind + \return SWITCH_STATUS_SUCCESS on suceess +*/ +SWITCH_DECLARE(switch_status_t) switch_core_event_hook_add_video_write_frame(switch_core_session_t *session, switch_video_write_frame_hook_t video_write_frame); + +/*! \brief Add an event hook to be executed when a session kills a channel \param session session to bind hook to \param kill_channel hook to bind Modified: freeswitch/trunk/src/include/switch_frame.h ============================================================================== --- freeswitch/trunk/src/include/switch_frame.h (original) +++ freeswitch/trunk/src/include/switch_frame.h Thu Apr 19 17:40:50 2007 @@ -30,7 +30,7 @@ * */ /*! \file switch_frame.h - \brief Media Frame Structure + \brief Media Frame Structure */ #ifndef SWITCH_FRAME_H @@ -40,7 +40,7 @@ SWITCH_BEGIN_EXTERN_C /*! \brief An abstraction of a data frame */ - struct switch_frame { +struct switch_frame { /*! a pointer to the codec information */ switch_codec_t *codec; /*! the originating source of the frame */ @@ -63,6 +63,9 @@ switch_payload_t payload; /*! the timestamp of the frame */ switch_size_t timestamp; + uint16_t seq; + uint32_t ssrc; + switch_bool_t m; /*! frame flags */ switch_frame_flag_t flags; }; Modified: freeswitch/trunk/src/include/switch_ivr.h ============================================================================== --- freeswitch/trunk/src/include/switch_ivr.h (original) +++ freeswitch/trunk/src/include/switch_ivr.h Thu Apr 19 17:40:50 2007 @@ -203,6 +203,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_inband_dtmf_session(switch_core_session_t *session); SWITCH_DECLARE(switch_status_t) switch_ivr_stop_inband_dtmf_session(switch_core_session_t *session); +SWITCH_DECLARE(void) switch_ivr_session_echo(switch_core_session_t *session); /*! \brief play a file from the disk to the session Modified: freeswitch/trunk/src/include/switch_module_interfaces.h ============================================================================== --- freeswitch/trunk/src/include/switch_module_interfaces.h (original) +++ freeswitch/trunk/src/include/switch_module_interfaces.h Thu Apr 19 17:40:50 2007 @@ -99,6 +99,10 @@ switch_status_t (*receive_event) (switch_core_session_t *, switch_event_t *); /*! change a sessions channel state */ switch_status_t (*state_change) (switch_core_session_t *); + /*! read a video frame from a session */ + switch_status_t (*read_video_frame) (switch_core_session_t *, switch_frame_t **, int, switch_io_flag_t, int); + /*! write a video frame to a session */ + switch_status_t (*write_video_frame) (switch_core_session_t *, switch_frame_t *, int, switch_io_flag_t, int); }; /*! \brief Abstraction of an module endpoint interface Modified: freeswitch/trunk/src/include/switch_types.h ============================================================================== --- freeswitch/trunk/src/include/switch_types.h (original) +++ freeswitch/trunk/src/include/switch_types.h Thu Apr 19 17:40:50 2007 @@ -110,6 +110,10 @@ #define SWITCH_LOCAL_MEDIA_PORT_VARIABLE "local_media_port" #define SWITCH_REMOTE_MEDIA_IP_VARIABLE "remote_media_ip" #define SWITCH_REMOTE_MEDIA_PORT_VARIABLE "remote_media_port" +#define SWITCH_REMOTE_VIDEO_IP_VARIABLE "remote_video_ip" +#define SWITCH_REMOTE_VIDEO_PORT_VARIABLE "remote_video_port" +#define SWITCH_LOCAL_VIDEO_IP_VARIABLE "local_video_ip" +#define SWITCH_LOCAL_VIDEO_PORT_VARIABLE "local_video_port" #define SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE "hangup_after_bridge" #define SWITCH_MAX_FORWARDS_VARIABLE "max_forwards" #define SWITCH_SPEECH_KEY "speech" @@ -542,6 +546,7 @@ CF_BREAK = (1 << 19) - Channel should stop what it's doing CF_BROADCAST = (1 << 20) - Channel is broadcasting CF_UNICAST = (1 << 21) - Channel has a unicast connection +CF_VIDEO = (1 << 22) - Channel has video </pre> */ @@ -567,7 +572,8 @@ CF_RING_READY = (1 << 18), CF_BREAK = (1 << 19), CF_BROADCAST = (1 << 20), - CF_UNICAST = (1 << 21) + CF_UNICAST = (1 << 21), + CF_VIDEO = (1 << 22) } switch_channel_flag_t; @@ -578,12 +584,14 @@ <pre> SFF_CNG = (1 << 0) - Frame represents comfort noise SFF_RAW_RTP = (1 << 1) - Frame has raw rtp accessible +SFF_RTP_HEADER = (1 << 2) - Get the rtp header from the frame header </pre> */ typedef enum { SFF_NONE = 0, SFF_CNG = (1 << 0), - SFF_RAW_RTP = (1 << 1) + SFF_RAW_RTP = (1 << 1), + SFF_RTP_HEADER = (1 << 2) } switch_frame_flag_t; Added: freeswitch/trunk/src/mod/codecs/mod_h26x/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/src/mod/codecs/mod_h26x/Makefile Thu Apr 19 17:40:50 2007 @@ -0,0 +1,2 @@ +BASE=../../../.. +include /usr/src/freeswitch.trunk/build/modmake.rules Added: freeswitch/trunk/src/mod/codecs/mod_h26x/mod_h26x.c ============================================================================== --- (empty file) +++ freeswitch/trunk/src/mod/codecs/mod_h26x/mod_h26x.c Thu Apr 19 17:40:50 2007 @@ -0,0 +1,154 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com> + * + * 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 <anthmct@yahoo.com> + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II <anthmct@yahoo.com> + * + * + * mod_h26x.c -- H26X Signed Linear Codec + * + */ +#include <switch.h> + +static const char modname[] = "mod_h26x"; + + +static switch_status_t switch_h26x_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) +{ + int encoding, decoding; + + encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); + decoding = (flags & SWITCH_CODEC_FLAG_DECODE); + + if (!(encoding || decoding)) { + return SWITCH_STATUS_FALSE; + } else { + return SWITCH_STATUS_SUCCESS; + } +} + +static switch_status_t switch_h26x_encode(switch_codec_t *codec, + switch_codec_t *other_codec, + void *decoded_data, + uint32_t decoded_data_len, + uint32_t decoded_rate, void *encoded_data, uint32_t * encoded_data_len, uint32_t * encoded_rate, + unsigned int *flag) +{ + return SWITCH_STATUS_FALSE; +} + +static switch_status_t switch_h26x_decode(switch_codec_t *codec, + switch_codec_t *other_codec, + void *encoded_data, + uint32_t encoded_data_len, + uint32_t encoded_rate, void *decoded_data, uint32_t * decoded_data_len, uint32_t * decoded_rate, + unsigned int *flag) +{ + return SWITCH_STATUS_FALSE; +} + + +static switch_status_t switch_h26x_destroy(switch_codec_t *codec) +{ + + return SWITCH_STATUS_SUCCESS; +} + +static const switch_codec_implementation_t h264_90000_implementation = { + /*.codec_type */ SWITCH_CODEC_TYPE_VIDEO, + /*.ianacode */ 99, + /*.iananame */ "H264", + /*.fmtp */ NULL, + /*.samples_per_second = */ 90000, + /*.bits_per_second = */ 0, + /*.microseconds_per_frame = */ 0, + /*.samples_per_frame = */ 0, + /*.bytes_per_frame = */ 0, + /*.encoded_bytes_per_frame = */ 0, + /*.number_of_channels = */ 1, + /*.pref_frames_per_packet = */ 1, + /*.max_frames_per_packet = */ 1, + /*.init = */ switch_h26x_init, + /*.encode = */ switch_h26x_encode, + /*.decode = */ switch_h26x_decode, + /*.destroy = */ switch_h26x_destroy + /*.next = */ +}; + +static const switch_codec_implementation_t h263_90000_implementation = { + /*.codec_type */ SWITCH_CODEC_TYPE_VIDEO, + /*.ianacode */ 34, + /*.iananame */ "H263", + /*.fmtp */ NULL, + /*.samples_per_second = */ 90000, + /*.bits_per_second = */ 0, + /*.microseconds_per_frame = */ 0, + /*.samples_per_frame = */ 0, + /*.bytes_per_frame = */ 0, + /*.encoded_bytes_per_frame = */ 0, + /*.number_of_channels = */ 1, + /*.pref_frames_per_packet = */ 1, + /*.max_frames_per_packet = */ 1, + /*.init = */ switch_h26x_init, + /*.encode = */ switch_h26x_encode, + /*.decode = */ switch_h26x_decode, + /*.destroy = */ switch_h26x_destroy, + /*.next = */&h264_90000_implementation +}; + +static const switch_codec_interface_t h26x_codec_interface = { + /*.interface_name */ "h26x video (passthru)", + /*.implementations */ &h263_90000_implementation +}; + +static switch_loadable_module_interface_t h26x_module_interface = { + /*.module_name */ modname, + /*.endpoint_interface */ NULL, + /*.timer_interface */ NULL, + /*.dialplan_interface */ NULL, + /*.codec_interface */ &h26x_codec_interface, + /*.application_interface */ NULL, + /*.api_interface */ NULL, +}; + + +SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename) +{ + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = &h26x_module_interface; + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab: + */ Added: freeswitch/trunk/src/mod/codecs/mod_h26x/mod_h26x.vcproj ============================================================================== --- (empty file) +++ freeswitch/trunk/src/mod/codecs/mod_h26x/mod_h26x.vcproj Thu Apr 19 17:40:50 2007 @@ -0,0 +1,211 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="mod_h26x" + ProjectGUID="{5844AFE1-AA3E-4BDB-A9EF-119AEF19DF88}" + RootNamespace="mod_h26x" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="2" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + CommandLine="" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories=""$(InputDir)..\..\..\include";"$(InputDir)include";"$(InputDir)..\..\..\..\libs\include";"$(InputDir)..\..\..\..\libs\libresample\include"" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="4" + WarnAsError="true" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="$(SolutionDir)$(OutDir)/mod/$(InputName).dll" + LinkIncremental="1" + AdditionalLibraryDirectories=""$(InputDir)..\..\..\..\libs\libresample\win";..\..\..\..\w32\vsnet\$(OutDir)" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(OutDir)$(TargetName).pdb" + SubSystem="2" + ImportLibrary="$(OutDir)/mod_h26x.lib" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="2" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + CommandLine="" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories=""$(InputDir)..\..\..\include";"$(InputDir)include";"$(InputDir)..\..\..\..\libs\include";"$(InputDir)..\..\..\..\libs\libresample\include"" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS" + RuntimeLibrary="2" + UsePrecompiledHeader="0" + WarningLevel="4" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="$(SolutionDir)$(OutDir)/mod/$(InputName).dll" + LinkIncremental="1" + AdditionalLibraryDirectories=""$(InputDir)..\..\..\..\libs\libresample\win";..\..\..\..\w32\vsnet\$(OutDir)" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(OutDir)$(TargetName).pdb" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + ImportLibrary="$(OutDir)/mod_h26x.lib" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath=".\mod_h26x.c" + > + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c Thu Apr 19 17:40:50 2007 @@ -58,6 +58,8 @@ switch_memory_pool_t **pool); static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, switch_io_flag_t flags, int stream_id); static switch_status_t sofia_write_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, switch_io_flag_t flags, int stream_id); +static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, switch_io_flag_t flags, int stream_id); +static switch_status_t sofia_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, switch_io_flag_t flags, int stream_id); static switch_status_t sofia_kill_channel(switch_core_session_t *session, int sig); @@ -321,12 +323,13 @@ } -static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, switch_io_flag_t flags, int stream_id) + +static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, switch_io_flag_t flags, int stream_id) { private_object_t *tech_pvt = NULL; switch_channel_t *channel = NULL; int payload = 0; - + channel = switch_core_session_get_channel(session); assert(channel != NULL); @@ -337,7 +340,7 @@ return SWITCH_STATUS_FALSE; } - while (!(tech_pvt->read_codec.implementation && switch_rtp_ready(tech_pvt->rtp_session))) { + while (!(tech_pvt->video_read_codec.implementation && switch_rtp_ready(tech_pvt->video_rtp_session))) { if (switch_channel_ready(channel)) { switch_yield(10000); } else { @@ -346,18 +349,112 @@ } - tech_pvt->read_frame.datalen = 0; - switch_set_flag_locked(tech_pvt, TFLAG_READING); + tech_pvt->video_read_frame.datalen = 0; -#if 0 - if (tech_pvt->last_read) { - elapsed = (unsigned int) ((switch_time_now() - tech_pvt->last_read) / 1000); - if (elapsed > 60000) { - return SWITCH_STATUS_TIMEOUT; + + if (switch_test_flag(tech_pvt, TFLAG_IO)) { + switch_status_t status; + + if (!switch_test_flag(tech_pvt, TFLAG_RTP)) { + return SWITCH_STATUS_GENERR; + } + + assert(tech_pvt->rtp_session != NULL); + tech_pvt->video_read_frame.datalen = 0; + + while (switch_test_flag(tech_pvt, TFLAG_IO) && tech_pvt->video_read_frame.datalen == 0) { + tech_pvt->video_read_frame.flags = SFF_NONE; + + status = switch_rtp_zerocopy_read_frame(tech_pvt->video_rtp_session, &tech_pvt->video_read_frame); + if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { + return SWITCH_STATUS_FALSE; + } + + payload = tech_pvt->video_read_frame.payload; + + if (tech_pvt->video_read_frame.datalen > 0) { + break; + } } } -#endif + if (tech_pvt->video_read_frame.datalen == 0) { + *frame = NULL; + return SWITCH_STATUS_GENERR; + } + + *frame = &tech_pvt->video_read_frame; + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t sofia_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, switch_io_flag_t flags, int stream_id) +{ + private_object_t *tech_pvt; + switch_channel_t *channel = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = (private_object_t *) switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + while (!(tech_pvt->video_read_codec.implementation && switch_rtp_ready(tech_pvt->video_rtp_session))) { + if (switch_channel_ready(channel)) { + switch_yield(10000); + } else { + return SWITCH_STATUS_GENERR; + } + } + + if (switch_test_flag(tech_pvt, TFLAG_HUP)) { + return SWITCH_STATUS_FALSE; + } + + if (!switch_test_flag(tech_pvt, TFLAG_RTP)) { + return SWITCH_STATUS_GENERR; + } + + if (!switch_test_flag(tech_pvt, TFLAG_IO)) { + return SWITCH_STATUS_SUCCESS; + } + + if (!switch_test_flag(frame, SFF_CNG)) { + switch_rtp_write_frame(tech_pvt->video_rtp_session, frame, 0); + } + + return status; +} + + +static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, switch_io_flag_t flags, int stream_id) +{ + private_object_t *tech_pvt = NULL; + switch_channel_t *channel = NULL; + int payload = 0; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = (private_object_t *) switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + if (switch_test_flag(tech_pvt, TFLAG_HUP)) { + return SWITCH_STATUS_FALSE; + } + + while (!(tech_pvt->read_codec.implementation && switch_rtp_ready(tech_pvt->rtp_session))) { + if (switch_channel_ready(channel)) { + switch_yield(10000); + } else { + return SWITCH_STATUS_GENERR; + } + } + + + tech_pvt->read_frame.datalen = 0; + switch_set_flag_locked(tech_pvt, TFLAG_READING); if (switch_test_flag(tech_pvt, TFLAG_IO)) { switch_status_t status; @@ -382,20 +479,6 @@ payload = tech_pvt->read_frame.payload; -#if 0 - elapsed = (unsigned int) ((switch_time_now() - started) / 1000); - - if (timeout > -1) { - if (elapsed >= (unsigned int) timeout) { - return SWITCH_STATUS_BREAK; - } - } - - elapsed = (unsigned int) ((switch_time_now() - last_act) / 1000); - if (elapsed >= hard_timeout) { - return SWITCH_STATUS_BREAK; - } -#endif if (switch_rtp_has_dtmf(tech_pvt->rtp_session)) { char dtmf[128]; switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, dtmf, sizeof(dtmf)); @@ -508,6 +591,9 @@ if (switch_rtp_ready(tech_pvt->rtp_session)) { switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_BREAK); } + if (switch_rtp_ready(tech_pvt->video_rtp_session)) { + switch_rtp_set_flag(tech_pvt->video_rtp_session, SWITCH_RTP_FLAG_BREAK); + } break; case SWITCH_SIG_KILL: default: @@ -517,6 +603,9 @@ if (switch_rtp_ready(tech_pvt->rtp_session)) { switch_rtp_kill_socket(tech_pvt->rtp_session); } + if (switch_rtp_ready(tech_pvt->video_rtp_session)) { + switch_rtp_kill_socket(tech_pvt->video_rtp_session); + } break; } @@ -774,7 +863,10 @@ /*.waitfor_read */ sofia_waitfor_write, /*.send_dtmf */ sofia_send_dtmf, /*.receive_message */ sofia_receive_message, - /*.receive_event */ sofia_receive_event + /*.receive_event */ sofia_receive_event, + /*.state_change*/ NULL, + /*.read_video_frame*/ sofia_read_video_frame, + /*.write_video_frame*/ sofia_write_video_frame }; static const switch_state_handler_table_t sofia_event_handlers = { Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h Thu Apr 19 17:40:50 2007 @@ -137,7 +137,9 @@ TFLAG_BUGGY_2833 = (1 << 21), TFLAG_SIP_HOLD = (1 << 22), TFLAG_INB_NOMEDIA = (1 << 23), - TFLAG_LATE_NEGOTIATION = (1 << 24) + TFLAG_LATE_NEGOTIATION = (1 << 24), + TFLAG_SDP = (1 << 25), + TFLAG_VIDEO = (1 << 26) } TFLAGS; struct mod_sofia_globals { @@ -310,7 +312,23 @@ nua_handle_t *nh; nua_handle_t *nh2; sip_contact_t *contact; - int hangup_status; + /** VIDEO **/ + switch_frame_t video_read_frame; + switch_codec_t video_read_codec; + switch_codec_t video_write_codec; + switch_rtp_t *video_rtp_session; + switch_port_t adv_sdp_video_port; + switch_port_t local_sdp_video_port; + char *video_rm_encoding; + switch_payload_t video_pt; + unsigned long video_rm_rate; + uint32_t video_codec_ms; + char *remote_sdp_video_ip; + switch_port_t remote_sdp_video_port; + char *video_rm_fmtp; + switch_payload_t video_agreed_pt; + char *video_fmtp_out; + uint32_t video_count; }; struct callback_t { @@ -428,3 +446,4 @@ switch_core_db_callback_func_t callback, void *pdata); char *sofia_glue_execute_sql2str(sofia_profile_t *profile, switch_mutex_t *mutex, char *sql, char *resbuf, size_t len); +void sofia_glue_check_video_codecs(private_object_t *tech_pvt); Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c Thu Apr 19 17:40:50 2007 @@ -924,14 +924,8 @@ nua_ack(nh, TAG_END()); break; case nua_callstate_received: - - if (session && switch_core_session_running(session)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Re-Entering Call State Received!\n"); - goto done; - } - - if (channel) { - if (r_sdp) { + if (tech_pvt && !switch_test_flag(tech_pvt, TFLAG_SDP)) { + if (r_sdp && !switch_test_flag(tech_pvt, TFLAG_SDP)) { if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOMEDIA"); switch_set_flag_locked(tech_pvt, TFLAG_READY); @@ -1015,7 +1009,7 @@ break; case nua_callstate_completed: if (tech_pvt && r_sdp) { - if (r_sdp) { + if (r_sdp) { // && !switch_test_flag(tech_pvt, TFLAG_SDP)) { if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) { goto done; } else { @@ -1078,10 +1072,10 @@ goto done; } - if (!r_sdp) { + if (!r_sdp && !switch_test_flag(tech_pvt, TFLAG_SDP)) { r_sdp = (const char *) switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE); } - if (r_sdp) { + if (r_sdp && !switch_test_flag(tech_pvt, TFLAG_SDP)) { if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) { switch_set_flag_locked(tech_pvt, TFLAG_ANS); switch_channel_mark_answered(channel); Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c Thu Apr 19 17:40:50 2007 @@ -34,6 +34,8 @@ */ #include "mod_sofia.h" +switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt); +switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int force); void sofia_glue_set_local_sdp(private_object_t *tech_pvt, char *ip, uint32_t port, char *sr, int force) { @@ -41,6 +43,7 @@ switch_time_t now = switch_time_now(); int ptime = 0; int rate = 0; + uint32_t v_port; if (!force && !ip && !sr && switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) { return; @@ -56,6 +59,8 @@ port = tech_pvt->proxy_sdp_audio_port; } } + + if (!sr) { sr = "sendrecv"; } @@ -63,7 +68,10 @@ snprintf(buf, sizeof(buf), "v=0\n" "o=FreeSWITCH %d%" SWITCH_TIME_T_FMT " %d%" SWITCH_TIME_T_FMT " IN IP4 %s\n" - "s=FreeSWITCH\n" "c=IN IP4 %s\n" "t=0 0\n" "a=%s\n" "m=audio %d RTP/AVP", port, now, port, now, ip, ip, sr, port); + "s=FreeSWITCH\n" + "c=IN IP4 %s\n" "t=0 0\n" + "a=%s\n" + "m=audio %d RTP/AVP", port, now, port, now, ip, ip, sr, port); if (tech_pvt->rm_encoding) { snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %d", tech_pvt->pt); @@ -72,6 +80,10 @@ for (i = 0; i < tech_pvt->num_codecs; i++) { const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; + if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) { + continue; + } + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %d", imp->ianacode); if (!ptime) { ptime = imp->microseconds_per_frame / 1000; @@ -105,6 +117,10 @@ const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; uint32_t rfc_3551_sucks = imp->samples_per_second; + if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) { + continue; + } + if (!rate) { rate = imp->samples_per_second; } @@ -136,6 +152,65 @@ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=ptime:%d\n", ptime); } + + if (switch_test_flag(tech_pvt, TFLAG_VIDEO)) { + sofia_glue_tech_choose_video_port(tech_pvt); + if ((v_port = tech_pvt->adv_sdp_video_port)) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "m=video %d RTP/AVP", v_port); + sofia_glue_tech_set_video_codec(tech_pvt, 0); + + + /*****************************/ + if (tech_pvt->video_rm_encoding) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %d", tech_pvt->video_pt); + } else if (tech_pvt->num_codecs) { + int i; + for (i = 0; i < tech_pvt->num_codecs; i++) { + const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; + + if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) { + continue; + } + + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %d", imp->ianacode); + if (!ptime) { + ptime = imp->microseconds_per_frame / 1000; + } + } + } + + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "\n"); + + if (tech_pvt->rm_encoding) { + rate = tech_pvt->video_rm_rate; + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=rtpmap:%d %s/%ld\n", tech_pvt->video_pt, tech_pvt->video_rm_encoding, tech_pvt->video_rm_rate); + if (tech_pvt->video_fmtp_out) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->video_pt, tech_pvt->video_fmtp_out); + } + } else if (tech_pvt->num_codecs) { + int i; + for (i = 0; i < tech_pvt->num_codecs; i++) { + const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; + + if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) { + continue; + } + + if (!rate) { + rate = imp->samples_per_second; + } + + + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=rtpmap:%d %s/%d\n", imp->ianacode, imp->iananame, imp->samples_per_second); + if (imp->fmtp) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=fmtp:%d %s\n", imp->ianacode, imp->fmtp); + } + } + } + } + } + /*****************************/ + tech_pvt->local_sdp_str = switch_core_session_strdup(tech_pvt->session, buf); } @@ -146,11 +221,11 @@ char *ocodec = NULL; if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) { - return; + goto end; } if (tech_pvt->num_codecs) { - return; + goto end; } assert(tech_pvt->session != NULL); @@ -192,6 +267,26 @@ sizeof(tech_pvt->codecs) / sizeof(tech_pvt->codecs[0])); } + end: + + sofia_glue_check_video_codecs(tech_pvt); + +} + +void sofia_glue_check_video_codecs(private_object_t *tech_pvt) +{ + if (tech_pvt->num_codecs && !switch_test_flag(tech_pvt, TFLAG_VIDEO)) { + int i; + + for (i = 0; i < tech_pvt->num_codecs; i++) { + if (tech_pvt->codecs[i]->codec_type == SWITCH_CODEC_TYPE_VIDEO) { + tech_pvt->video_count++; + } + } + if (tech_pvt->video_count) { + switch_set_flag_locked(tech_pvt, TFLAG_VIDEO); + } + } } @@ -297,6 +392,42 @@ return SWITCH_STATUS_SUCCESS; } + + +switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt) +{ + char *ip = tech_pvt->profile->rtpip; + switch_channel_t *channel; + switch_port_t sdp_port; + char tmp[50]; + + channel = switch_core_session_get_channel(tech_pvt->session); + + if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA) || tech_pvt->adv_sdp_video_port) { + return SWITCH_STATUS_SUCCESS; + } + + + tech_pvt->local_sdp_video_port = switch_rtp_request_port(); + sdp_port = tech_pvt->local_sdp_video_port; + + if (tech_pvt->profile->extrtpip) { + if (sofia_glue_ext_address_lookup(&ip, &sdp_port, tech_pvt->profile->extrtpip, switch_core_session_get_pool(tech_pvt->session)) != + SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_FALSE; + } + } + + tech_pvt->adv_sdp_video_port = sdp_port; + + snprintf(tmp, sizeof(tmp), "%d", sdp_port); + switch_channel_set_variable(channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip); + switch_channel_set_variable(channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE, tmp); + + + return SWITCH_STATUS_SUCCESS; +} + switch_status_t sofia_glue_do_invite(switch_core_session_t *session) { char rpid[1024] = { 0 }; @@ -555,6 +686,77 @@ } switch_rtp_destroy(&tech_pvt->rtp_session); } + if (switch_rtp_ready(tech_pvt->video_rtp_session)) { + switch_rtp_destroy(&tech_pvt->video_rtp_session); + } +} + +switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int force) +{ + switch_channel_t *channel; + + if (tech_pvt->video_read_codec.implementation) { + if (!force) { + return SWITCH_STATUS_SUCCESS; + } + if (strcasecmp(tech_pvt->video_read_codec.implementation->iananame, tech_pvt->video_rm_encoding) || + tech_pvt->video_read_codec.implementation->samples_per_second != tech_pvt->video_rm_rate) { + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Changing Codec from %s to %s\n", + tech_pvt->video_read_codec.implementation->iananame, tech_pvt->video_rm_encoding); + switch_core_codec_destroy(&tech_pvt->video_read_codec); + switch_core_codec_destroy(&tech_pvt->video_write_codec); + //switch_core_session_reset(tech_pvt->session); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Already using %s\n", tech_pvt->video_read_codec.implementation->iananame); + return SWITCH_STATUS_SUCCESS; + } + } + + channel = switch_core_session_get_channel(tech_pvt->session); + assert(channel != NULL); + + if (!tech_pvt->video_rm_encoding) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec with no name?\n"); + return SWITCH_STATUS_FALSE; + } + + if (switch_core_codec_init(&tech_pvt->video_read_codec, + tech_pvt->video_rm_encoding, + tech_pvt->video_rm_fmtp, + tech_pvt->video_rm_rate, + 0, + //tech_pvt->video_codec_ms, + 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"); + return SWITCH_STATUS_FALSE; + } else { + if (switch_core_codec_init(&tech_pvt->video_write_codec, + tech_pvt->video_rm_encoding, + tech_pvt->video_rm_fmtp, + tech_pvt->video_rm_rate, + 0,//tech_pvt->video_codec_ms, + 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"); + return SWITCH_STATUS_FALSE; + } else { + int ms; + tech_pvt->video_read_frame.rate = tech_pvt->video_rm_rate; + ms = tech_pvt->video_write_codec.implementation->microseconds_per_frame / 1000; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set VIDEO Codec %s %s/%ld %d ms\n", + switch_channel_get_name(channel), tech_pvt->video_rm_encoding, tech_pvt->video_rm_rate, tech_pvt->video_codec_ms); + tech_pvt->video_read_frame.codec = &tech_pvt->video_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); + tech_pvt->fmtp_out = switch_core_session_strdup(tech_pvt->session, tech_pvt->video_write_codec.fmtp_out); + } + } + return SWITCH_STATUS_SUCCESS; } switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force) @@ -625,6 +827,9 @@ } + + + switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt) { int bw, ms; @@ -674,7 +879,7 @@ flags |= SWITCH_RTP_FLAG_AUTO_CNG; } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n", switch_channel_get_name(channel), tech_pvt->local_sdp_audio_ip, tech_pvt->local_sdp_audio_port, @@ -690,9 +895,9 @@ if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port, &err) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTP REPORTS ERROR: [%s]\n", err); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err); } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RTP CHANGING DEST TO: [%s:%d]\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n", tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); /* Reactivate the NAT buster flag. */ switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_AUTOADJ); @@ -722,7 +927,7 @@ if ((vad_in && inb) || (vad_out && !inb)) { switch_rtp_enable_vad(tech_pvt->rtp_session, tech_pvt->session, &tech_pvt->read_codec, SWITCH_VAD_FLAG_TALKING); switch_set_flag_locked(tech_pvt, TFLAG_VAD); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RTP Engage VAD for %s ( %s %s )\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AUDIO RTP Engage VAD for %s ( %s %s )\n", switch_channel_get_name(switch_core_session_get_channel(tech_pvt->session)), vad_in ? "in" : "", vad_out ? "out" : ""); } @@ -732,6 +937,41 @@ if (tech_pvt->cng_pt) { switch_rtp_set_cng_pt(tech_pvt->rtp_session, tech_pvt->cng_pt); } + + sofia_glue_check_video_codecs(tech_pvt); + + if (switch_test_flag(tech_pvt, TFLAG_VIDEO) && tech_pvt->video_rm_encoding) { + flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_NOBLOCK | SWITCH_RTP_FLAG_RAW_WRITE); + + sofia_glue_tech_set_video_codec(tech_pvt, 0); + + tech_pvt->video_rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip, + tech_pvt->local_sdp_video_port, + tech_pvt->remote_sdp_video_ip, + tech_pvt->remote_sdp_video_port, + tech_pvt->video_agreed_pt, + tech_pvt->video_read_codec.implementation->samples_per_frame, + 0,//tech_pvt->video_codec_ms * 1000, + (switch_rtp_flag_t) flags, + NULL, + NULL,//tech_pvt->profile->timer_name, + &err, switch_core_session_get_pool(tech_pvt->session)); + + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "VIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n", + switch_channel_get_name(channel), + tech_pvt->local_sdp_audio_ip, + tech_pvt->local_sdp_video_port, + tech_pvt->remote_sdp_video_ip, + tech_pvt->remote_sdp_video_port, tech_pvt->video_agreed_pt, + 0,//tech_pvt->video_read_codec.implementation->microseconds_per_frame / 1000, + switch_rtp_ready(tech_pvt->video_rtp_session) ? "SUCCESS" : err); + + + if (switch_rtp_ready(tech_pvt->video_rtp_session)) { + switch_channel_set_flag(channel, CF_VIDEO); + } + } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTP REPORTS ERROR: [%s]\n", err); @@ -783,8 +1023,6 @@ return SWITCH_STATUS_FALSE; } - - uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *sdp) { uint8_t match = 0; @@ -811,6 +1049,7 @@ if (switch_strlen_zero(a->a_name)) { continue; } + if (!strcasecmp(a->a_name, "sendonly")) { if (!switch_test_flag(tech_pvt, TFLAG_SIP_HOLD)) { char *stream; @@ -840,15 +1079,17 @@ sdp_connection_t *connection; ptime = dptime; - for (a = m->m_attributes; a; a = a->a_next) { - if (!strcasecmp(a->a_name, "ptime") && a->a_value) { - ptime = atoi(a->a_value); - } - } + if (m->m_type == sdp_media_audio) { sdp_rtpmap_t *map; + for (a = m->m_attributes; a; a = a->a_next) { + if (!strcasecmp(a->a_name, "ptime") && a->a_value) { + ptime = atoi(a->a_value); + } + } + connection = sdp->sdp_connection; if (m->m_connections) { connection = m->m_connections; @@ -896,14 +1137,18 @@ for (i = 0; i < tech_pvt->num_codecs; i++) { const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Codec Compare [%s:%d]/[%s:%d]\n", + + if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) { + continue; + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d]/[%s:%d]\n", rm_encoding, map->rm_pt, imp->iananame, imp->ianacode); if (map->rm_pt < 96) { match = (map->rm_pt == imp->ianacode) ? 1 : 0; } else { match = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1; } - + if (match && (map->rm_rate == imp->samples_per_second)) { if (ptime && ptime * 1000 != imp->microseconds_per_frame) { near_match = imp; @@ -963,9 +1208,83 @@ } } } + } else if (m->m_type == sdp_media_video) { + sdp_rtpmap_t *map; + const char *rm_encoding; + int framerate = 0; + const switch_codec_implementation_t *mimp = NULL; + int vmatch = 0, i; + + connection = sdp->sdp_connection; + if (m->m_connections) { + connection = m->m_connections; + } + + if (!connection) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n"); + match = 0; + break; + } + + for (map = m->m_rtpmaps; map; map = map->rm_next) { + + for (a = m->m_attributes; a; a = a->a_next) { + if (!strcasecmp(a->a_name, "framerate") && a->a_value) { + framerate = atoi(a->a_value); + } + } + if (!(rm_encoding = map->rm_encoding)) { + rm_encoding = ""; + } + + for (i = 0; i < tech_pvt->num_codecs; i++) { + const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; + + if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) { + continue; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d]/[%s:%d]\n", + rm_encoding, map->rm_pt, imp->iananame, imp->ianacode); + if (map->rm_pt < 96) { + vmatch = (map->rm_pt == imp->ianacode) ? 1 : 0; + } else { + vmatch = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1; + } + + + if (vmatch && (map->rm_rate == imp->samples_per_second)) { + mimp = imp; + break; + } else { + vmatch = 0; + } + } + + if (mimp) { + if ((tech_pvt->video_rm_encoding = switch_core_session_strdup(session, (char *) rm_encoding))) { + char tmp[50]; + tech_pvt->video_pt = (switch_payload_t) map->rm_pt; + tech_pvt->video_rm_rate = map->rm_rate; + tech_pvt->video_codec_ms = mimp->microseconds_per_frame / 1000; + tech_pvt->remote_sdp_video_ip = switch_core_session_strdup(session, (char *) connection->c_address); + tech_pvt->video_rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp); + tech_pvt->remote_sdp_video_port = (switch_port_t) m->m_port; + tech_pvt->video_agreed_pt = (switch_payload_t) map->rm_pt; + snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_video_port); + switch_channel_set_variable(channel, SWITCH_REMOTE_VIDEO_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip); + switch_channel_set_variable(channel, SWITCH_REMOTE_VIDEO_PORT_VARIABLE, tmp); + } else { + vmatch = 0; + } + } + } } + } + switch_set_flag_locked(tech_pvt, TFLAG_SDP); + return match; } Modified: freeswitch/trunk/src/switch_core_event_hook.c ============================================================================== --- freeswitch/trunk/src/switch_core_event_hook.c (original) +++ freeswitch/trunk/src/switch_core_event_hook.c Thu Apr 19 17:40:50 2007 @@ -118,6 +118,50 @@ } +SWITCH_DECLARE(switch_status_t) switch_core_event_hook_add_video_read_frame(switch_core_session_t *session, switch_video_read_frame_hook_t video_read_frame) +{ + switch_io_event_hook_video_read_frame_t *hook, *ptr; + + assert(video_read_frame != NULL); + if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) { + hook->video_read_frame = video_read_frame; + if (!session->event_hooks.video_read_frame) { + session->event_hooks.video_read_frame = hook; + } else { + for (ptr = session->event_hooks.video_read_frame; ptr && ptr->next; ptr = ptr->next); + ptr->next = hook; + + } + + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_MEMERR; + +} + +SWITCH_DECLARE(switch_status_t) switch_core_event_hook_add_video_write_frame(switch_core_session_t *session, switch_video_write_frame_hook_t video_write_frame) +{ + switch_io_event_hook_video_write_frame_t *hook, *ptr; + + assert(video_write_frame != NULL); + if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) { + hook->video_write_frame = video_write_frame; + if (!session->event_hooks.video_write_frame) { + session->event_hooks.video_write_frame = hook; + } else { + for (ptr = session->event_hooks.video_write_frame; ptr && ptr->next; ptr = ptr->next); + ptr->next = hook; + + } + + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_MEMERR; + +} + SWITCH_DECLARE(switch_status_t) switch_core_event_hook_add_kill_channel(switch_core_session_t *session, switch_kill_channel_hook_t kill_channel) { switch_io_event_hook_kill_channel_t *hook, *ptr; Modified: freeswitch/trunk/src/switch_core_io.c ============================================================================== --- freeswitch/trunk/src/switch_core_io.c (original) +++ freeswitch/trunk/src/switch_core_io.c Thu Apr 19 17:40:50 2007 @@ -35,6 +35,61 @@ #include "private/switch_core.h" +SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, int stream_id) +{ + switch_io_event_hook_video_write_frame_t *ptr; + switch_status_t status = SWITCH_STATUS_FALSE; + switch_io_flag_t flags = 0; + if (session->endpoint_interface->io_routines->write_video_frame) { + if ((status = session->endpoint_interface->io_routines->write_video_frame(session, frame, timeout, flags, stream_id)) == SWITCH_STATUS_SUCCESS) { + for (ptr = session->event_hooks.video_write_frame; ptr; ptr = ptr->next) { + if ((status = ptr->video_write_frame(session, frame, timeout, flags, stream_id)) != SWITCH_STATUS_SUCCESS) { + break; + } + } + } + } + return status; +} + +SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, int stream_id) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + switch_io_event_hook_video_read_frame_t *ptr; + + if (session->endpoint_interface->io_routines->read_video_frame) { + if ((status = + session->endpoint_interface->io_routines->read_video_frame(session, frame, timeout, SWITCH_IO_FLAG_NOOP, stream_id)) == SWITCH_STATUS_SUCCESS) { + for (ptr = session->event_hooks.video_read_frame; ptr; ptr = ptr->next) { + if ((status = ptr->video_read_frame(session, frame, timeout, SWITCH_IO_FLAG_NOOP, stream_id)) != SWITCH_STATUS_SUCCESS) { + break; + } + } + } + } + + if (status != SWITCH_STATUS_SUCCESS) { + goto done; + } + + if (!(*frame)) { + goto done; + } + + assert(session != NULL); + assert(*frame != NULL); + + if (switch_test_flag(*frame, SFF_CNG)) { + status = SWITCH_STATUS_SUCCESS; + goto done; + } + + done: + + return status; +} + + SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, int stream_id) { switch_io_event_hook_read_frame_t *ptr; @@ -128,6 +183,10 @@ session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); session->raw_read_frame.rate = read_frame->rate; session->raw_read_frame.timestamp = read_frame->timestamp; + 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; read_frame = &session->raw_read_frame; break; case SWITCH_STATUS_NOOP: @@ -139,6 +198,10 @@ 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; + 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; read_frame = &session->raw_read_frame; status = SWITCH_STATUS_SUCCESS; break; @@ -244,6 +307,10 @@ session->enc_read_frame.codec = session->read_codec; session->enc_read_frame.samples = session->read_codec->implementation->bytes_per_frame / sizeof(int16_t); session->enc_read_frame.timestamp = read_frame->timestamp; + 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; session->enc_read_frame.payload = session->read_codec->implementation->ianacode; *frame = &session->enc_read_frame; break; @@ -252,6 +319,9 @@ session->raw_read_frame.samples = enc_frame->codec->implementation->samples_per_frame; session->raw_read_frame.timestamp = read_frame->timestamp; session->raw_read_frame.payload = enc_frame->codec->implementation->ianacode; + session->raw_read_frame.m = read_frame->m; + session->raw_read_frame.ssrc = read_frame->ssrc; + session->raw_read_frame.seq = read_frame->seq; *frame = &session->raw_read_frame; status = SWITCH_STATUS_SUCCESS; break; @@ -371,6 +441,10 @@ 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: @@ -500,12 +574,18 @@ session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); session->enc_write_frame.timestamp = frame->timestamp; session->enc_write_frame.payload = session->write_codec->implementation->ianacode; + 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; @@ -553,6 +633,9 @@ session->enc_write_frame.codec = session->write_codec; session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); session->enc_write_frame.timestamp = frame->timestamp; + session->enc_write_frame.m = frame->m; + session->enc_write_frame.ssrc = frame->ssrc; + session->enc_write_frame.seq = frame->seq; session->enc_write_frame.payload = session->write_codec->implementation->ianacode; write_frame = &session->enc_write_frame; if (!session->read_resampler) { @@ -571,6 +654,9 @@ session->enc_write_frame.codec = session->write_codec; session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); session->enc_write_frame.timestamp = frame->timestamp; + session->enc_write_frame.m = frame->m; + session->enc_write_frame.ssrc = frame->ssrc; + session->enc_write_frame.seq = frame->seq; session->enc_write_frame.payload = session->write_codec->implementation->ianacode; write_frame = &session->enc_write_frame; break; @@ -578,6 +664,9 @@ 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->ssrc = frame->ssrc; + enc_frame->seq = frame->seq; enc_frame->payload = enc_frame->codec->implementation->ianacode; write_frame = enc_frame; status = SWITCH_STATUS_SUCCESS; Modified: freeswitch/trunk/src/switch_core_state_machine.c ============================================================================== --- freeswitch/trunk/src/switch_core_state_machine.c (original) +++ freeswitch/trunk/src/switch_core_state_machine.c Thu Apr 19 17:40:50 2007 @@ -181,18 +181,9 @@ static void switch_core_standard_on_loopback(switch_core_session_t *session) { - switch_frame_t *frame; - int stream_id; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard LOOPBACK\n"); - - while (switch_channel_get_state(session->channel) == CS_LOOPBACK) { - for (stream_id = 0; stream_id < session->stream_count; stream_id++) { - if (switch_core_session_read_frame(session, &frame, -1, stream_id) == SWITCH_STATUS_SUCCESS) { - switch_core_session_write_frame(session, frame, -1, stream_id); - } - } - } + switch_ivr_session_echo(session); } static void switch_core_standard_on_transmit(switch_core_session_t *session) Modified: freeswitch/trunk/src/switch_ivr_async.c ============================================================================== --- freeswitch/trunk/src/switch_ivr_async.c (original) +++ freeswitch/trunk/src/switch_ivr_async.c Thu Apr 19 17:40:50 2007 @@ -31,6 +31,71 @@ */ #include <switch.h> +struct echo_helper { + switch_core_session_t *session; + int up; +}; + +static void *SWITCH_THREAD_FUNC echo_video_thread(switch_thread_t *thread, void *obj) +{ + struct echo_helper *eh = obj; + switch_core_session_t *session = eh->session; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_status_t status; + switch_frame_t *read_frame; + + eh->up = 1; + while(switch_channel_ready(channel) && switch_channel_get_state(channel) == CS_LOOPBACK) { + status = switch_core_session_read_video_frame(session, &read_frame, -1, 0); + + if (!SWITCH_READ_ACCEPTABLE(status)) { + break; + } + + switch_core_session_write_video_frame(session, read_frame, -1, 0); + + } + eh->up = 0; + return NULL; +} + +SWITCH_DECLARE(void) switch_ivr_session_echo(switch_core_session_t *session) +{ + switch_status_t status; + switch_frame_t *read_frame; + struct echo_helper eh = {0}; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_thread_t *thread; + switch_threadattr_t *thd_attr = NULL; + + + switch_channel_answer(channel); + + if (switch_channel_test_flag(channel, CF_VIDEO)) { + eh.session = session; + switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session)); + switch_threadattr_detach_set(thd_attr, 1); + switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); + switch_thread_create(&thread, thd_attr, echo_video_thread, &eh, switch_core_session_get_pool(session)); + } + + while(switch_channel_ready(channel) && switch_channel_get_state(channel) == CS_LOOPBACK) { + status = switch_core_session_read_frame(session, &read_frame, -1, 0); + if (!SWITCH_READ_ACCEPTABLE(status)) { + break; + } + switch_core_session_write_frame(session, read_frame, -1, 0); + } + + if (eh.up) { + while(eh.up) { + switch_yield(1000); + } + } +} + + + static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { switch_file_handle_t *fh = (switch_file_handle_t *) user_data; Modified: freeswitch/trunk/src/switch_rtp.c ============================================================================== --- freeswitch/trunk/src/switch_rtp.c (original) +++ freeswitch/trunk/src/switch_rtp.c Thu Apr 19 17:40:50 2007 @@ -352,8 +352,7 @@ rtp_session->sock = new_sock; new_sock = NULL; - if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) - || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK)) { + if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK)) { switch_socket_opt_set(rtp_session->sock, SWITCH_SO_NONBLOCK, TRUE); switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_NOBLOCK); } @@ -803,7 +802,7 @@ while (switch_rtp_ready(rtp_session)) { bytes = sizeof(rtp_msg_t); status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock, 0, (void *) &rtp_session->recv_msg, &bytes); - + if (!SWITCH_STATUS_IS_BREAK(status) && rtp_session->timer.interval) { switch_core_timer_step(&rtp_session->timer); } @@ -900,7 +899,11 @@ if (status == SWITCH_STATUS_BREAK || bytes == 0) { if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_DATAWAIT)) { - switch_yield((rtp_session->ms_per_packet / 1000) * 750); + if (rtp_session->ms_per_packet) { + switch_yield((rtp_session->ms_per_packet / 1000) * 750); + } else { + switch_yield(1000); + } continue; } return 0; @@ -1136,13 +1139,16 @@ } bytes = rtp_common_read(rtp_session, &frame->payload, &frame->flags); - + frame->data = rtp_session->recv_msg.body; frame->packet = &rtp_session->recv_msg; frame->packetlen = bytes; frame->source = __FILE__; frame->flags |= SFF_RAW_RTP; frame->timestamp = ntohl(rtp_session->recv_msg.header.ts); + frame->seq = ntohs(rtp_session->recv_msg.header.seq); + frame->ssrc = ntohl(rtp_session->recv_msg.header.ssrc); + frame->m = rtp_session->recv_msg.header.m ? SWITCH_TRUE : SWITCH_FALSE; if (bytes < 0) { frame->datalen = 0; @@ -1153,8 +1159,11 @@ } else { bytes -= rtp_header_len; } - + frame->datalen = bytes; + + + return SWITCH_STATUS_SUCCESS; } @@ -1350,7 +1359,6 @@ switch_core_timer_check(&rtp_session->timer); rtp_session->last_write_samplecount = rtp_session->timer.samplecount; } - switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *) send_msg, &bytes); } @@ -1478,6 +1486,12 @@ payload = rtp_session->payload; } + if (switch_test_flag(frame, SFF_RTP_HEADER)) { + return switch_rtp_write_manual(rtp_session, frame->data, frame->datalen, frame->m, frame->payload, + frame->timestamp, frame->seq, frame->ssrc, &frame->flags); + } + + if (fwd) { data = frame->packet; len = frame->packetlen; @@ -1551,7 +1565,7 @@ } return (int) bytes; - //return rtp_common_write(rtp_session, (void *) &send_msg, rtp_header_len + datalen, m, payload, NULL); + //return rtp_common_write(rtp_session, (void *) &send_msg, rtp_header_len + datalen, m, payload); } SWITCH_DECLARE(uint32_t) switch_rtp_get_ssrc(switch_rtp_t *rtp_session)
participants (1)
-
Freeswitch SVN