[Freeswitch-svn] [commit] r4977 - in freeswitch/trunk/src: . include mod/codecs/mod_h26x mod/endpoints/mod_sofia
Freeswitch SVN
anthm at freeswitch.org
Thu Apr 19 17:40:50 EDT 2007
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 at 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 at yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II <anthmct at 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)
More information about the Freeswitch-svn
mailing list