diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln index cd22423f5b..588637f438 100644 --- a/Freeswitch.2010.sln +++ b/Freeswitch.2010.sln @@ -529,6 +529,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzrtp", "libs\libzrtp\pro EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_redis", "src\mod\applications\mod_redis\mod_redis.2010.vcxproj", "{886B5E9D-F2C2-4AF2-98C8-EF98C4C770E6}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download libjpeg", "libs\win32\Download libjpeg.2010.vcxproj", "{652AD5F7-8488-489F-AAD0-7FBE064703B6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libjpeg", "libs\win32\libjpeg\libjpeg.2010.vcxproj", "{019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution All|Win32 = All|Win32 @@ -3608,6 +3612,38 @@ Global {886B5E9D-F2C2-4AF2-98C8-EF98C4C770E6}.Release|x64.ActiveCfg = Release|x64 {886B5E9D-F2C2-4AF2-98C8-EF98C4C770E6}.Release|x64 Setup.ActiveCfg = Release|x64 {886B5E9D-F2C2-4AF2-98C8-EF98C4C770E6}.Release|x86 Setup.ActiveCfg = Release|x64 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.All|Win32.ActiveCfg = Release|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.All|Win32.Build.0 = Release|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.All|x64.ActiveCfg = Release|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.All|x64 Setup.ActiveCfg = Release|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.All|x86 Setup.ActiveCfg = Release|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.Debug|Win32.ActiveCfg = Debug|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.Debug|Win32.Build.0 = Debug|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.Debug|x64.ActiveCfg = Debug|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.Debug|x86 Setup.ActiveCfg = Debug|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.Release|Win32.ActiveCfg = Release|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.Release|Win32.Build.0 = Release|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.Release|x64.ActiveCfg = Release|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.Release|x64 Setup.ActiveCfg = Release|Win32 + {652AD5F7-8488-489F-AAD0-7FBE064703B6}.Release|x86 Setup.ActiveCfg = Release|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.All|Win32.ActiveCfg = Release|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.All|Win32.Build.0 = Release|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.All|x64.ActiveCfg = Release|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.All|x64 Setup.ActiveCfg = Release|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.All|x86 Setup.ActiveCfg = Release|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Debug|Win32.ActiveCfg = Debug|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Debug|Win32.Build.0 = Debug|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Debug|x64.ActiveCfg = Debug|x64 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Debug|x64.Build.0 = Debug|x64 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Debug|x64 Setup.ActiveCfg = Release|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Debug|x86 Setup.ActiveCfg = Release|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Release|Win32.ActiveCfg = Release|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Release|Win32.Build.0 = Release|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Release|x64.ActiveCfg = Release|x64 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Release|x64.Build.0 = Release|x64 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Release|x64 Setup.ActiveCfg = Release|Win32 + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Release|x86 Setup.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3723,6 +3759,7 @@ Global {23B4D303-79FC-49E0-89E2-2280E7E28940} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {26C82FCE-E0CF-4D10-A00C-D8E582FFEB53} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {C13CC324-0032-4492-9A30-310A6BD64FF5} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {EC3E5C7F-EE09-47E2-80FE-546363D14A98} = {B8F5B47B-8568-46EB-B320-64C17D2A98BC} {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F} = {0C808854-54D1-4230-BFF5-77B5FD905000} {ACFFF684-4D19-4D48-AF12-88EA1D778BDF} = {0C808854-54D1-4230-BFF5-77B5FD905000} @@ -3761,6 +3798,7 @@ Global {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19} = {C120A020-773F-4EA3-923F-B67AF28B750D} {B808178B-82F0-4CF4-A2B1-921939FA24D0} = {C120A020-773F-4EA3-923F-B67AF28B750D} {D578E676-7EC8-4548-BD8B-845C635F14AD} = {C120A020-773F-4EA3-923F-B67AF28B750D} + {652AD5F7-8488-489F-AAD0-7FBE064703B6} = {C120A020-773F-4EA3-923F-B67AF28B750D} {988CACF7-3FCB-4992-BE69-77872AE67DC8} = {6CD61A1D-797C-470A-BE08-8C31B68BB336} {5BC072DB-3826-48EA-AF34-FE32AA01E83B} = {6CD61A1D-797C-470A-BE08-8C31B68BB336} {FA429E98-8B03-45E6-A096-A4BC5E821DE4} = {6CD61A1D-797C-470A-BE08-8C31B68BB336} diff --git a/libs/spandsp/src/libspandsp.2010.vcxproj b/libs/spandsp/src/libspandsp.2010.vcxproj index 253863f975..0ef3d481b0 100644 --- a/libs/spandsp/src/libspandsp.2010.vcxproj +++ b/libs/spandsp/src/libspandsp.2010.vcxproj @@ -76,7 +76,7 @@ Disabled - .;..\..\src\spandsp;..\..\src;..\..\src\msvc;.\spandsp;.\msvc;..\..\tiff-3.8.2\libtiff;%(AdditionalIncludeDirectories) + .;..\..\src\spandsp;..\..\src;..\..\src\msvc;.\spandsp;.\msvc;..\..\tiff-3.8.2\libtiff;..\..\jpeg-8d;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBSPANDSP_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;%(PreprocessorDefinitions) true EnableFastChecks @@ -97,7 +97,7 @@ $(IntDir)BuildLog $(ProjectName).htm - .;.\spandsp;.\msvc;..\..\tiff-3.8.2\libtiff;%(AdditionalIncludeDirectories) + .;.\spandsp;.\msvc;..\..\tiff-3.8.2\libtiff;..\..\jpeg-8d;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBSPANDSP_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;%(PreprocessorDefinitions) MultiThreadedDLL Level4 @@ -118,7 +118,7 @@ Disabled - .;.\spandsp;.\msvc;..\..\tiff-3.8.2\libtiff;%(AdditionalIncludeDirectories) + .;.\spandsp;.\msvc;..\..\tiff-3.8.2\libtiff;..\..\jpeg-8d;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBSPANDSP_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;%(PreprocessorDefinitions) true EnableFastChecks @@ -139,7 +139,7 @@ $(IntDir)BuildLog $(ProjectName).htm - .;.\spandsp;.\msvc;..\..\tiff-3.8.2\libtiff;%(AdditionalIncludeDirectories) + .;.\spandsp;.\msvc;..\..\tiff-3.8.2\libtiff;..\..\jpeg-8d;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBSPANDSP_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;%(PreprocessorDefinitions) MultiThreadedDLL Level4 @@ -208,6 +208,7 @@ + @@ -409,6 +410,14 @@ + + {019dbd2a-273d-4ba4-bf86-b5efe2ed76b1} + true + false + false + true + false + {401a40cd-5db4-4e34-ac68-fa99e9fac014} false diff --git a/libs/spandsp/src/libspandsp.2010.vcxproj.filters b/libs/spandsp/src/libspandsp.2010.vcxproj.filters index 0c445ef07c..c7d1210235 100644 --- a/libs/spandsp/src/libspandsp.2010.vcxproj.filters +++ b/libs/spandsp/src/libspandsp.2010.vcxproj.filters @@ -277,6 +277,9 @@ Source Files + + Source Files + diff --git a/libs/spandsp/src/msvc/config.h b/libs/spandsp/src/msvc/config.h index a1eaae16a6..42494d345f 100644 --- a/libs/spandsp/src/msvc/config.h +++ b/libs/spandsp/src/msvc/config.h @@ -74,6 +74,8 @@ #define _MMX_H_ + #define cbrtf(value) pow((float)value, (float).333) + #include // To get alloca #endif diff --git a/libs/spandsp/src/t42.c b/libs/spandsp/src/t42.c index f7f7e1e062..a9eb7afc9c 100644 --- a/libs/spandsp/src/t42.c +++ b/libs/spandsp/src/t42.c @@ -929,7 +929,7 @@ SPAN_DECLARE(int) t42_srgb_to_itulab(logging_state_t *logging, lab_params_t *s, for (pos = 0; pos < srclen; pos += compressor.image_width*compressor.num_components) { - scan_line_in = src + pos; + scan_line_in = (JSAMPROW)src + pos; srgb_to_lab(s, scan_line_out, scan_line_in, compressor.image_width); jpeg_write_scanlines(&compressor, &scan_line_out, 1); } @@ -1033,7 +1033,7 @@ SPAN_DECLARE(int) t42_itulab_to_itulab(logging_state_t *logging, tdata_t *dst, t for (pos = 0; pos < srclen; pos += compressor.image_width*compressor.num_components) { - scan_line_in = src + pos; + scan_line_in = (JSAMPROW)src + pos; jpeg_write_scanlines(&compressor, &scan_line_in, 1); } @@ -1150,7 +1150,7 @@ SPAN_DECLARE(int) t42_itulab_to_srgb(logging_state_t *logging, lab_params_t *s, for (pos = 0; decompressor.output_scanline < decompressor.output_height; pos += decompressor.output_width*decompressor.num_components) { - scan_line_out = dst + pos; + scan_line_out = (JSAMPROW)dst + pos; jpeg_read_scanlines(&decompressor, &scan_line_in, 1); lab_to_srgb(s, scan_line_out, scan_line_in, decompressor.output_width); } diff --git a/libs/win32/Download libjpeg.2010.vcxproj b/libs/win32/Download libjpeg.2010.vcxproj new file mode 100644 index 0000000000..56844e037c --- /dev/null +++ b/libs/win32/Download libjpeg.2010.vcxproj @@ -0,0 +1,81 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + Download libjpeg + {652AD5F7-8488-489F-AAD0-7FBE064703B6} + Download libjpeg + Win32Proj + + + + Utility + MultiByte + + + Utility + MultiByte + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(PlatformName)\jpeg-8d\$(Configuration)\ + $(PlatformName)\jpeg-8d\$(Configuration)\ + + + + $(IntDir)BuildLog $(ProjectName).htm + + + + + + + + + $(IntDir)BuildLog $(ProjectName).htm + + + + + + + + + + + + + Document + Downloading libjpeg. + if not exist "$(ProjectDir)..\jpeg-8d" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://www.ijg.org/files/jpegsrc.v8d.tar.gz "$(ProjectDir).." + + $(ProjectDir)..\jpeg-8d;%(Outputs) + Downloading libjpeg. + if not exist "$(ProjectDir)..\jpeg-8d" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://www.ijg.org/files/jpegsrc.v8d.tar.gz "$(ProjectDir).." + + $(ProjectDir)..\jpeg-8d;%(Outputs) + + + + + + \ No newline at end of file diff --git a/libs/win32/libjpeg/libjpeg.2010.vcxproj b/libs/win32/libjpeg/libjpeg.2010.vcxproj new file mode 100644 index 0000000000..734f4b8446 --- /dev/null +++ b/libs/win32/libjpeg/libjpeg.2010.vcxproj @@ -0,0 +1,226 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Disabled + Disabled + Disabled + Disabled + false + false + false + false + + + + libjpeg + {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1} + Win32Proj + libjpeg + + + + StaticLibrary + false + true + Unicode + + + StaticLibrary + false + true + Unicode + + + StaticLibrary + false + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + NotUsing + Full + true + false + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS + true + true + ..\..\jpeg-8d;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + + + + + Level3 + NotUsing + Full + true + false + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS + true + true + ..\..\jpeg-8d;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + + + + + Level3 + NotUsing + Full + true + false + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS + true + true + ..\..\jpeg-8d;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + + + if not exist "$(ProjectDir)..\..\jpeg-8d\jconfig.h" type "$(ProjectDir)..\..\jpeg-8d\jconfig.vc" > "$(ProjectDir)..\..\jpeg-8d\jconfig.h" + + + + + Level3 + NotUsing + Full + true + false + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS + true + true + ..\..\jpeg-8d;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + + + if not exist "$(ProjectDir)..\..\jpeg-8d\jconfig.h" type "$(ProjectDir)..\..\jpeg-8d\jconfig.vc" > "$(ProjectDir)..\..\jpeg-8d\jconfig.h" + + + + + + \ No newline at end of file diff --git a/libs/win32/libjpeg/libjpeg.2010.vcxproj.filters b/libs/win32/libjpeg/libjpeg.2010.vcxproj.filters new file mode 100644 index 0000000000..6a63450cb4 --- /dev/null +++ b/libs/win32/libjpeg/libjpeg.2010.vcxproj.filters @@ -0,0 +1,186 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.2010.vcxproj b/src/mod/endpoints/mod_sofia/mod_sofia.2010.vcxproj index 5432c3323f..c5b0b0772f 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.2010.vcxproj +++ b/src/mod/endpoints/mod_sofia/mod_sofia.2010.vcxproj @@ -138,6 +138,7 @@ + diff --git a/src/mod/endpoints/mod_sofia/rtp.c b/src/mod/endpoints/mod_sofia/rtp.c new file mode 100644 index 0000000000..9e927402e7 --- /dev/null +++ b/src/mod/endpoints/mod_sofia/rtp.c @@ -0,0 +1,667 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, Anthony Minessale II + * + * 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 + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Mathieu Rene + * + * rtp.c -- RTP Controllable Channel Module + * + */ + +#include +#include "mod_sofia.h" + +#define kLOCALADDR "local_addr" +#define kLOCALPORT "local_port" +#define kREMOTEADDR "remote_addr" +#define kREMOTEPORT "remote_port" +#define kCODEC "codec" +#define kPTIME "ptime" +#define kPT "pt" +#define kRFC2833PT "rfc2833_pt" +#define kMODE "mode" +#define kRATE "rate" + +static struct { + switch_memory_pool_t *pool; + switch_endpoint_interface_t *endpoint_interface; +} crtp; + +typedef struct { + switch_core_session_t *session; + switch_channel_t *channel; + switch_codec_t read_codec, write_codec; + switch_frame_t read_frame; + + + + switch_rtp_bug_flag_t rtp_bugs; + switch_rtp_t *rtp_session; + + uint32_t timestamp_send; + + const char *local_address; + const char *remote_address; + const char *codec; + int ptime; + + const switch_codec_implementation_t *negotiated_codecs[SWITCH_MAX_CODECS]; + int num_negotiated_codecs; + + char *origin; + + switch_port_t local_port; + switch_port_t remote_port; + switch_payload_t agreed_pt; /*XXX*/ + sofia_dtmf_t dtmf_type; + enum { + RTP_SENDONLY, + RTP_RECVONLY, + RTP_SENDRECV + } mode; +} crtp_private_t; + +static switch_status_t channel_on_init(switch_core_session_t *session); +static switch_status_t channel_on_destroy(switch_core_session_t *session); +static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, + switch_caller_profile_t *outbound_profile, + switch_core_session_t **new_session, + switch_memory_pool_t **pool, + switch_originate_flag_t flags, switch_call_cause_t *cancel_cause); +static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); +static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); +static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg); +static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf); +static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event); + +switch_state_handler_table_t crtp_state_handlers = { + /*on_init */channel_on_init, + /*on_routing */ NULL, + /*on_execute */ NULL, + /*on_hangup*/ NULL, + /*on_exchange_media*/ NULL, + /*on_soft_execute*/ NULL, + /*on_consume_media*/ NULL, + /*on_hibernate*/ NULL, + /*on_reset*/ NULL, + /*on_park*/ NULL, + /*on_reporting*/ NULL, + /*on_destroy*/ channel_on_destroy + +}; + +switch_io_routines_t crtp_io_routines = { + /*outgoing_channel*/ channel_outgoing_channel, + /*read_frame*/ channel_read_frame, + /*write_frame*/ channel_write_frame, + /*kill_channel*/ NULL, + /*send_dtmf*/ channel_send_dtmf, + /*receive_message*/ channel_receive_message, + /*receive_event*/ channel_receive_event, + /*state_change*/ NULL, + /*read_video_frame*/ NULL, + /*write_video_frame*/ NULL, + /*state_run*/ NULL, + /* resurrect_session*/ NULL + +}; + + +void crtp_init(switch_loadable_module_interface_t *module_interface) +{ + switch_endpoint_interface_t *endpoint_interface; + //switch_api_interface_t *api_interface; + + crtp.pool = module_interface->pool; + endpoint_interface = switch_loadable_module_create_interface(module_interface, SWITCH_ENDPOINT_INTERFACE); + endpoint_interface->interface_name = "rtp"; + endpoint_interface->io_routines = &crtp_io_routines; + endpoint_interface->state_handler = &crtp_state_handlers; + crtp.endpoint_interface = endpoint_interface; + + //SWITCH_ADD_API(api_interface, "rtp_test", "test", test_function, ""); +} + +static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, + switch_caller_profile_t *outbound_profile, + switch_core_session_t **new_session, + switch_memory_pool_t **pool, + switch_originate_flag_t flags, switch_call_cause_t *cancel_cause) +{ + switch_channel_t *channel; + char name[128]; + crtp_private_t *tech_pvt = NULL; + switch_caller_profile_t *caller_profile; + + const char *err; + + + const char *local_addr = switch_event_get_header_nil(var_event, kLOCALADDR), + *szlocal_port = switch_event_get_header_nil(var_event, kLOCALPORT), + *remote_addr = switch_event_get_header_nil(var_event, kREMOTEADDR), + *szremote_port = switch_event_get_header_nil(var_event, kREMOTEPORT), + *codec = switch_event_get_header_nil(var_event, kCODEC), + *szptime = switch_event_get_header_nil(var_event, kPTIME), + //*mode = switch_event_get_header_nil(var_event, kMODE), + //*szrfc2833_pt = switch_event_get_header_nil(var_event, kRFC2833PT), + *szrate = switch_event_get_header_nil(var_event, kRATE), + *szpt = switch_event_get_header_nil(var_event, kPT); + + + switch_port_t local_port = !zstr(szlocal_port) ? atoi(szlocal_port) : 0, + remote_port = !zstr(szremote_port) ? atoi(szremote_port) : 0; + + int ptime = !zstr(szptime) ? atoi(szptime) : 0, + //rfc2833_pt = !zstr(szrfc2833_pt) ? atoi(szrfc2833_pt) : 0, + rate = !zstr(szrate) ? atoi(szrate) : 8000, + pt = !zstr(szpt) ? atoi(szpt) : 0; + + if ( + ((zstr(remote_addr) || remote_port == 0) && (zstr(local_addr) || local_port == 0)) || + zstr(codec) || + zstr(szpt)) { + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing required arguments\n"); + goto fail; + } + + + if (!(*new_session = switch_core_session_request(crtp.endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, 0, pool))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't request session.\n"); + goto fail; + } + + channel = switch_core_session_get_channel(*new_session); + + tech_pvt = switch_core_session_alloc(*new_session, sizeof *tech_pvt); + tech_pvt->session = *new_session; + tech_pvt->channel = channel; + tech_pvt->local_address = switch_core_session_strdup(*new_session, local_addr); + tech_pvt->local_port = local_port; + tech_pvt->remote_address = switch_core_session_strdup(*new_session, remote_addr); + tech_pvt->remote_port = remote_port; + tech_pvt->ptime = ptime; + tech_pvt->agreed_pt = pt; + tech_pvt->dtmf_type = DTMF_2833; /* XXX */ + + if (zstr(local_addr) || local_port == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "The local address and port must be set\n"); + goto fail; + } else if (zstr(remote_addr) || remote_port == 0) { + tech_pvt->mode = RTP_RECVONLY; + } else { + tech_pvt->mode = RTP_SENDRECV; + } + + switch_core_session_set_private(*new_session, tech_pvt); + + caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); + switch_channel_set_caller_profile(channel, caller_profile); + + + snprintf(name, sizeof(name), "rtp/%s", outbound_profile->destination_number); + switch_channel_set_name(channel, name); + + switch_channel_set_state(channel, CS_INIT); + + if (switch_core_codec_init(&tech_pvt->read_codec, + codec, + NULL, + rate, + ptime, + 1, + /*SWITCH_CODEC_FLAG_ENCODE |*/ SWITCH_CODEC_FLAG_DECODE, + NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); + goto fail; + } else { + if (switch_core_codec_init(&tech_pvt->write_codec, + codec, + NULL, + rate, + ptime, + 1, + SWITCH_CODEC_FLAG_ENCODE /*| SWITCH_CODEC_FLAG_DECODE*/, + NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); + goto fail; + } + } + + if (switch_core_session_set_read_codec(*new_session, &tech_pvt->read_codec) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set read codec?\n"); + goto fail; + } + + if (switch_core_session_set_write_codec(*new_session, &tech_pvt->write_codec) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set write codec?\n"); + goto fail; + } + + if (!(tech_pvt->rtp_session = switch_rtp_new(local_addr, local_port, remote_addr, remote_port, tech_pvt->agreed_pt, + tech_pvt->read_codec.implementation->samples_per_packet, ptime * 1000, + flags, "soft", &err, switch_core_session_get_pool(*new_session)))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't setup RTP session: [%s]\n", err); + goto fail; + } + + if (switch_core_session_thread_launch(*new_session) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't start session thread.\n"); + goto fail; + } + + switch_channel_mark_answered(channel); + + return SWITCH_CAUSE_SUCCESS; + +fail: + if (tech_pvt) { + if (tech_pvt->read_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->read_codec); + } + + if (tech_pvt->write_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->write_codec); + } + } + + if (*new_session) { + switch_core_session_destroy(new_session); + } + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; +} + +static switch_status_t channel_on_init(switch_core_session_t *session) +{ + + switch_channel_t *channel = switch_core_session_get_channel(session); + + switch_channel_set_state(channel, CS_CONSUME_MEDIA); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_on_destroy(switch_core_session_t *session) +{ + crtp_private_t *tech_pvt = switch_core_session_get_private(session); + + if ((tech_pvt = switch_core_session_get_private(session))) { + + if (tech_pvt->read_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->read_codec); + } + + if (tech_pvt->write_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->write_codec); + } + } + + return SWITCH_STATUS_SUCCESS; +} + + +static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) +{ + crtp_private_t *tech_pvt; + switch_channel_t *channel; + switch_status_t status; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + if (!tech_pvt->rtp_session || tech_pvt->mode == RTP_SENDONLY) { + switch_yield(20000); /* replace by local timer XXX */ + goto cng; + } + + if (switch_rtp_has_dtmf(tech_pvt->rtp_session)) { + switch_dtmf_t dtmf = { 0 }; + switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, &dtmf); + switch_channel_queue_dtmf(channel, &dtmf); + } + + tech_pvt->read_frame.flags = SFF_NONE; + tech_pvt->read_frame.codec = &tech_pvt->read_codec; + status = switch_rtp_zerocopy_read_frame(tech_pvt->rtp_session, &tech_pvt->read_frame, flags); + + if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { + goto cng; + } + + *frame = &tech_pvt->read_frame; + return SWITCH_STATUS_SUCCESS; + +cng: + *frame = &tech_pvt->read_frame; + tech_pvt->read_frame.codec = &tech_pvt->read_codec; + tech_pvt->read_frame.flags |= SFF_CNG; + tech_pvt->read_frame.datalen = 0; + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) +{ + crtp_private_t *tech_pvt; + switch_channel_t *channel; + //int frames = 0, bytes = 0, samples = 0; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + +#if 0 + if (!switch_test_flag(frame, SFF_CNG) && !switch_test_flag(frame, SFF_PROXY_PACKET)) { + if (tech_pvt->read_codec.implementation->encoded_bytes_per_packet) { + bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_packet; + frames = ((int) frame->datalen / bytes); + } else + frames = 1; + + samples = frames * tech_pvt->read_codec.implementation->samples_per_packet; + } + + tech_pvt->timestamp_send += samples; +#endif + if (tech_pvt->mode == RTP_RECVONLY) { + return SWITCH_STATUS_SUCCESS; + } + + switch_rtp_write_frame(tech_pvt->rtp_session, frame); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf) +{ + crtp_private_t *tech_pvt = NULL; + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + switch(tech_pvt->dtmf_type) { + case DTMF_2833: + { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Enqueuing RFC2833 DTMF %c of length %d\n", dtmf->digit, dtmf->duration); + return switch_rtp_queue_rfc2833(tech_pvt->rtp_session, dtmf); + } + case DTMF_NONE: + default: + { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Discarding DTMF %c of length %d, DTMF type is NONE\n", dtmf->digit, dtmf->duration); + } + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_bool_t compare_var(switch_event_t *event, switch_channel_t *channel, const char *varname) +{ + const char *chan_val = switch_channel_get_variable_dup(channel, varname, SWITCH_FALSE, -1); + const char *event_val = switch_event_get_header(event, varname); + + if (zstr(chan_val) || zstr(event_val)) { + return 1; + } + + return strcasecmp(chan_val, event_val); +} + +static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event) +{ + const char *command = switch_event_get_header(event, "command"); + switch_channel_t *channel = switch_core_session_get_channel(session); + crtp_private_t *tech_pvt = switch_core_session_get_private(session); + char *codec = switch_event_get_header_nil(event, kCODEC); + char *szptime = switch_event_get_header_nil(event, kPTIME); + char *szrate = switch_event_get_header_nil(event, kRATE); + char *szpt = switch_event_get_header_nil(event, kPT); + + int ptime = !zstr(szptime) ? atoi(szptime) : 0, + rate = !zstr(szrate) ? atoi(szrate) : 8000, + pt = !zstr(szpt) ? atoi(szpt) : 0; + + + if (!zstr(command) && !strcasecmp(command, "media_modify")) { + /* Compare parameters */ + if (compare_var(event, channel, kREMOTEADDR) || + compare_var(event, channel, kREMOTEPORT)) { + char *remote_addr = switch_event_get_header(event, kREMOTEADDR); + char *szremote_port = switch_event_get_header(event, kREMOTEPORT); + switch_port_t remote_port = !zstr(szremote_port) ? atoi(szremote_port) : 0; + const char *err; + + + switch_channel_set_variable(channel, kREMOTEADDR, remote_addr); + switch_channel_set_variable(channel, kREMOTEPORT, szremote_port); + + if (switch_rtp_set_remote_address(tech_pvt->rtp_session, remote_addr, remote_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error setting RTP remote address: %s\n", err); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set RTP remote: %s:%d\n", remote_addr, (int)remote_port); + tech_pvt->mode = RTP_SENDRECV; + } + } + + if (compare_var(event, channel, kCODEC) || + compare_var(event, channel, kPTIME) || + compare_var(event, channel, kPT) || + compare_var(event, channel, kRATE)) { + /* Reset codec */ + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Switching codec updating \n"); + + if (switch_core_codec_init(&tech_pvt->read_codec, + codec, + NULL, + rate, + ptime, + 1, + /*SWITCH_CODEC_FLAG_ENCODE |*/ SWITCH_CODEC_FLAG_DECODE, + NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); + goto fail; + } else { + if (switch_core_codec_init(&tech_pvt->write_codec, + codec, + NULL, + rate, + ptime, + 1, + SWITCH_CODEC_FLAG_ENCODE /*| SWITCH_CODEC_FLAG_DECODE*/, + NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); + goto fail; + } + } + + if (switch_core_session_set_read_codec(session, &tech_pvt->read_codec) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set read codec?\n"); + goto fail; + } + + if (switch_core_session_set_write_codec(session, &tech_pvt->write_codec) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set write codec?\n"); + goto fail; + } + + switch_rtp_set_default_payload(tech_pvt->rtp_session, pt); + switch_rtp_set_recv_pt(tech_pvt->rtp_session, pt); + } + + if (compare_var(event, channel, kRFC2833PT)) { + const char *szpt = switch_channel_get_variable(channel, kRFC2833PT); + int pt = !zstr(szpt) ? atoi(szpt) : 0; + + switch_channel_set_variable(channel, kRFC2833PT, szpt); + switch_rtp_set_telephony_event(tech_pvt->rtp_session, pt); + } + + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Received unknown command [%s] in event.\n", !command ? "null" : command); + } + + return SWITCH_STATUS_SUCCESS; +fail: + if (tech_pvt) { + if (tech_pvt->read_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->read_codec); + } + + if (tech_pvt->write_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->write_codec); + } + } + + if (session) { + switch_core_session_destroy(&session); + } + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + +} + +static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) +{ + crtp_private_t *tech_pvt = NULL; + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + switch (msg->message_id) { + case SWITCH_MESSAGE_INDICATE_DEBUG_AUDIO: + { + if (switch_rtp_ready(tech_pvt->rtp_session) && !zstr(msg->string_array_arg[0]) && !zstr(msg->string_array_arg[1])) { + int32_t flags = 0; + if (!strcasecmp(msg->string_array_arg[0], "read")) { + flags |= SWITCH_RTP_FLAG_DEBUG_RTP_READ; + } else if (!strcasecmp(msg->string_array_arg[0], "write")) { + flags |= SWITCH_RTP_FLAG_DEBUG_RTP_WRITE; + } else if (!strcasecmp(msg->string_array_arg[0], "both")) { + flags |= SWITCH_RTP_FLAG_DEBUG_RTP_READ | SWITCH_RTP_FLAG_DEBUG_RTP_WRITE; + } + + if (flags) { + if (switch_true(msg->string_array_arg[1])) { + switch_rtp_set_flag(tech_pvt->rtp_session, flags); + } else { + switch_rtp_clear_flag(tech_pvt->rtp_session, flags); + } + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Options\n"); + } + } + break; + } + case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC: + if (switch_rtp_ready(tech_pvt->rtp_session)) { + rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_ONCE); + } + break; + case SWITCH_MESSAGE_INDICATE_JITTER_BUFFER: + { + if (switch_rtp_ready(tech_pvt->rtp_session)) { + int len = 0, maxlen = 0, qlen = 0, maxqlen = 50, max_drift = 0; + + if (msg->string_arg) { + char *p, *q; + const char *s; + + if (!strcasecmp(msg->string_arg, "pause")) { + switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_TRUE); + goto end; + } else if (!strcasecmp(msg->string_arg, "resume")) { + switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_FALSE); + goto end; + } else if (!strncasecmp(msg->string_arg, "debug:", 6)) { + s = msg->string_arg + 6; + if (s && !strcmp(s, "off")) { + s = NULL; + } + switch_rtp_debug_jitter_buffer(tech_pvt->rtp_session, s); + goto end; + } + + + if ((len = atoi(msg->string_arg))) { + qlen = len / (tech_pvt->read_codec.implementation->microseconds_per_packet / 1000); + if (qlen < 1) { + qlen = 3; + } + } + + if (qlen) { + if ((p = strchr(msg->string_arg, ':'))) { + p++; + maxlen = atol(p); + if ((q = strchr(p, ':'))) { + q++; + max_drift = abs(atol(q)); + } + } + } + + + if (maxlen) { + maxqlen = maxlen / (tech_pvt->read_codec.implementation->microseconds_per_packet / 1000); + } + } + + if (qlen) { + if (maxqlen < qlen) { + maxqlen = qlen * 5; + } + if (switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen, maxqlen, + tech_pvt->read_codec.implementation->samples_per_packet, + tech_pvt->read_codec.implementation->samples_per_second, max_drift) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), + SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames) (%d max frames) (%d max drift)\n", + len, qlen, maxqlen, max_drift); + switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER); + if (!switch_false(switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_plc"))) { + switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER_PLC); + } + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), + SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", len, qlen); + } + + } else { + switch_rtp_deactivate_jitter_buffer(tech_pvt->rtp_session); + } + } + } + break; + + default: + break; + } +end: + return SWITCH_STATUS_SUCCESS; +} +