From: <sb...@us...> - 2007-10-31 19:01:28
|
Revision: 1251 http://iaxclient.svn.sourceforge.net/iaxclient/?rev=1251&view=rev Author: sbalea Date: 2007-10-31 12:01:27 -0700 (Wed, 31 Oct 2007) Log Message: ----------- Synchronize with trunk rev 1250 Revision Links: -------------- http://iaxclient.svn.sourceforge.net/iaxclient/?rev=1250&view=rev Modified Paths: -------------- branches/team/mihai/echocan/README.VisualStudio branches/team/mihai/echocan/contrib/tcl/iaxclient.c branches/team/mihai/echocan/contrib/win/vs2005/iaxclient.sln branches/team/mihai/echocan/lib/codec_theora.c branches/team/mihai/echocan/lib/iaxclient.h branches/team/mihai/echocan/lib/slice.c branches/team/mihai/echocan/lib/slice.h branches/team/mihai/echocan/lib/video.c branches/team/mihai/echocan/simpleclient/stresstest/stresstest.c branches/team/mihai/echocan/simpleclient/vtestcall/vtestcall.c Added Paths: ----------- branches/team/mihai/echocan/contrib/win/vs2005/libvidcap.vcproj Modified: branches/team/mihai/echocan/README.VisualStudio =================================================================== --- branches/team/mihai/echocan/README.VisualStudio 2007-10-31 17:31:21 UTC (rev 1250) +++ branches/team/mihai/echocan/README.VisualStudio 2007-10-31 19:01:27 UTC (rev 1251) @@ -28,18 +28,19 @@ http://www.microsoft.com/downloads/details.aspx?FamilyID=c2b1e300-f358-4523-b479-f53d234cdccf 2) Obtain dependencies. At the time of this writing, portaudio-v19, - libogg 1.1.3, speex 1.2beta1, and libtheora 1.0alpha7 are required. + libogg 1.1.3, speex 1.2beta1, libtheora 1.0alpha7, and libvidcap are required. Source for these dependencies are available here: http://portaudio.com/archives/pa_snapshot_v19.tar.gz http://downloads.xiph.org/releases/ogg/libogg-1.1.3.tar.gz http://downloads.xiph.org/releases/speex/speex-1.2beta1.tar.gz http://downloads.xiph.org/releases/theora/libtheora-1.0alpha7.tar.gz + http://downloads.sourceforge.net/libvidcap/libvidcap-0.1.tar.gz In order to build with the vcproj files provided by iaxclient, these dependent libraries must be moved to be peer directories to the iaxclient source directory. They also must have the following - names: libogg, speex, and libtheora. So the final directory + names: libogg, speex, libtheora and libvidcap. So the final directory layout would be as follows: C:\...\whereever\iaxclient @@ -47,6 +48,7 @@ C:\...\whereever\libogg C:\...\whereever\speex C:\...\whereever\libtheora + C:\...\whereever\libvidcap 2) Open the solution file: contrib/win/vs2005/iaxclient.sln Modified: branches/team/mihai/echocan/contrib/tcl/iaxclient.c =================================================================== --- branches/team/mihai/echocan/contrib/tcl/iaxclient.c 2007-10-31 17:31:21 UTC (rev 1250) +++ branches/team/mihai/echocan/contrib/tcl/iaxclient.c 2007-10-31 19:01:27 UTC (rev 1251) @@ -600,7 +600,9 @@ } if (objc == 2) { - line = iaxc_selected_call(); + // Problems reported coming from this line. + // If including it again you must be very sure of exactly what you do! + //line = iaxc_selected_call(); } if (objc == 3) { @@ -614,7 +616,9 @@ if (result == TCL_OK) { iaxc_call(num); - iaxc_select_call(line); + // Problems reported coming from this line. + // If including it again you must be very sure of exactly what you do! + //iaxc_select_call(line); } return result; } Modified: branches/team/mihai/echocan/contrib/win/vs2005/iaxclient.sln =================================================================== --- branches/team/mihai/echocan/contrib/win/vs2005/iaxclient.sln 2007-10-31 17:31:21 UTC (rev 1250) +++ branches/team/mihai/echocan/contrib/win/vs2005/iaxclient.sln 2007-10-31 19:01:27 UTC (rev 1251) @@ -7,14 +7,14 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libiaxclient", "libiaxclient.vcproj", "{9A9C003E-EAF6-4D0E-896F-E3994503C7E4}" ProjectSection(ProjectDependencies) = postProject + {82C9BD79-9796-405F-8A28-3F538514AC3A} = {82C9BD79-9796-405F-8A28-3F538514AC3A} + {3A76129B-55AB-4D54-BAA7-08F63ED52569} = {3A76129B-55AB-4D54-BAA7-08F63ED52569} + {5CC054B7-6DAA-46BF-9A08-3B33B83E8D3E} = {5CC054B7-6DAA-46BF-9A08-3B33B83E8D3E} + {2F463562-375D-481E-A6E0-7C7D0DC1ED7A} = {2F463562-375D-481E-A6E0-7C7D0DC1ED7A} + {E972C52F-9E85-4D65-B19C-031E511E9DB4} = {E972C52F-9E85-4D65-B19C-031E511E9DB4} + {E2C6AD95-7A61-41FE-8754-A4623C891BF8} = {E2C6AD95-7A61-41FE-8754-A4623C891BF8} + {F5166D99-32BB-40D5-BE95-6F97F72C44CE} = {F5166D99-32BB-40D5-BE95-6F97F72C44CE} {3B023516-2C69-4CCB-9302-239991B6EC2C} = {3B023516-2C69-4CCB-9302-239991B6EC2C} - {F5166D99-32BB-40D5-BE95-6F97F72C44CE} = {F5166D99-32BB-40D5-BE95-6F97F72C44CE} - {E2C6AD95-7A61-41FE-8754-A4623C891BF8} = {E2C6AD95-7A61-41FE-8754-A4623C891BF8} - {E972C52F-9E85-4D65-B19C-031E511E9DB4} = {E972C52F-9E85-4D65-B19C-031E511E9DB4} - {2F463562-375D-481E-A6E0-7C7D0DC1ED7A} = {2F463562-375D-481E-A6E0-7C7D0DC1ED7A} - {5CC054B7-6DAA-46BF-9A08-3B33B83E8D3E} = {5CC054B7-6DAA-46BF-9A08-3B33B83E8D3E} - {3A76129B-55AB-4D54-BAA7-08F63ED52569} = {3A76129B-55AB-4D54-BAA7-08F63ED52569} - {82C9BD79-9796-405F-8A28-3F538514AC3A} = {82C9BD79-9796-405F-8A28-3F538514AC3A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libiax2", "libiax2.vcproj", "{5CC054B7-6DAA-46BF-9A08-3B33B83E8D3E}" @@ -34,6 +34,11 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libvidcap", "..\..\..\..\libvidcap\contrib\win\vs2005\libvidcap.vcproj", "{F5166D99-32BB-40D5-BE95-6F97F72C44CE}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vtestcall", "..\..\..\simpleclient\vtestcall\vtestcall.vcproj", "{B5F8E725-85A8-4CB1-8824-B82127BB2B1E}" + ProjectSection(ProjectDependencies) = postProject + {9A9C003E-EAF6-4D0E-896F-E3994503C7E4} = {9A9C003E-EAF6-4D0E-896F-E3994503C7E4} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_dll|Win32 = Debug_dll|Win32 @@ -122,6 +127,14 @@ {F5166D99-32BB-40D5-BE95-6F97F72C44CE}.Release_dll|Win32.Build.0 = Release|Win32 {F5166D99-32BB-40D5-BE95-6F97F72C44CE}.Release|Win32.ActiveCfg = Release|Win32 {F5166D99-32BB-40D5-BE95-6F97F72C44CE}.Release|Win32.Build.0 = Release|Win32 + {B5F8E725-85A8-4CB1-8824-B82127BB2B1E}.Debug_dll|Win32.ActiveCfg = Debug|Win32 + {B5F8E725-85A8-4CB1-8824-B82127BB2B1E}.Debug_dll|Win32.Build.0 = Debug|Win32 + {B5F8E725-85A8-4CB1-8824-B82127BB2B1E}.Debug|Win32.ActiveCfg = Debug|Win32 + {B5F8E725-85A8-4CB1-8824-B82127BB2B1E}.Debug|Win32.Build.0 = Debug|Win32 + {B5F8E725-85A8-4CB1-8824-B82127BB2B1E}.Release_dll|Win32.ActiveCfg = Release|Win32 + {B5F8E725-85A8-4CB1-8824-B82127BB2B1E}.Release_dll|Win32.Build.0 = Release|Win32 + {B5F8E725-85A8-4CB1-8824-B82127BB2B1E}.Release|Win32.ActiveCfg = Release|Win32 + {B5F8E725-85A8-4CB1-8824-B82127BB2B1E}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Copied: branches/team/mihai/echocan/contrib/win/vs2005/libvidcap.vcproj (from rev 1250, trunk/contrib/win/vs2005/libvidcap.vcproj) =================================================================== --- branches/team/mihai/echocan/contrib/win/vs2005/libvidcap.vcproj (rev 0) +++ branches/team/mihai/echocan/contrib/win/vs2005/libvidcap.vcproj 2007-10-31 19:01:27 UTC (rev 1251) @@ -0,0 +1,361 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="libvidcap" + ProjectGUID="{F5166D99-32BB-40D5-BE95-6F97F72C44CE}" + RootNamespace="libvidcap" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(SolutionDir)\$(ConfigurationName)\$(ProjectName)" + IntermediateDirectory="$(OutDir)" + ConfigurationType="4" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\..\..\..\libvidcap\src;..\..\..\..\libvidcap\src\directshow;..\..\..\..\libvidcap\include;"$(DXSDK_DIR)\Include"" + PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;HAVE_DIRECTSHOW;HAVE_SLEEP" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="4" + CompileAs="1" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(SolutionDir)\$(ConfigurationName)\$(ProjectName)" + IntermediateDirectory="$(OutDir)" + ConfigurationType="4" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="..\..\..\..\libvidcap\src;..\..\..\..\libvidcap\src\directshow;..\..\..\..\libvidcap\include;"$(DXSDK_DIR)\Include"" + PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;HAVE_DIRECTSHOW;HAVE_SLEEP" + RuntimeLibrary="2" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + CompileAs="1" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath="..\..\..\..\libvidcap\src\conv.c" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\conv_to_i420.c" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\conv_to_rgb.c" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\conv_to_yuy2.c" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\directshow\DevMonitor.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\directshow\DirectShowSource.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\directshow\DShowSrcManager.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\directshow\GraphMonitor.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\hotlist.c" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\logging.c" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\sapi.c" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\sapi_dshow.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\sliding_window.c" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\vidcap.c" + > + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath="..\..\..\..\libvidcap\src\conv.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\include\vidcap\converters.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\directshow\DevMonitor.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\directshow\DirectShowSource.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\directshow\DShowSrcManager.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\directshow\GraphMonitor.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\hotlist.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\directshow\LocklessQueue.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\logging.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\logging.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\sapi.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\sapi_context.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\src\sliding_window.h" + > + </File> + <File + RelativePath="..\..\..\..\libvidcap\include\vidcap\vidcap.h" + > + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> Modified: branches/team/mihai/echocan/lib/codec_theora.c =================================================================== --- branches/team/mihai/echocan/lib/codec_theora.c 2007-10-31 17:31:21 UTC (rev 1250) +++ branches/team/mihai/echocan/lib/codec_theora.c 2007-10-31 19:01:27 UTC (rev 1251) @@ -111,7 +111,8 @@ free(c); } -static int decode(struct iaxc_video_codec *c, int inlen, char *in, int *outlen, char *out) +static int decode(struct iaxc_video_codec *c, int inlen, const char *in, + int *outlen, char *out) { struct theora_decoder *d; ogg_packet op; Modified: branches/team/mihai/echocan/lib/iaxclient.h =================================================================== --- branches/team/mihai/echocan/lib/iaxclient.h 2007-10-31 17:31:21 UTC (rev 1250) +++ branches/team/mihai/echocan/lib/iaxclient.h 2007-10-31 19:01:27 UTC (rev 1251) @@ -132,6 +132,8 @@ #define IAXC_EVENT_DTMF 9 /*!< Indicates a DTMF event */ #define IAXC_EVENT_AUDIO 10 /*!< Indicates an audio event */ #define IAXC_EVENT_VIDEOSTATS 11 /*!< Indicates a video statistics update event */ +#define IAXC_EVENT_VIDCAP_ERROR 12 /*!< Indicates a video capture error occurred */ +#define IAXC_EVENT_VIDCAP_DEVICE 13 /*!< Indicates a possible video capture device insertion/removal */ #define IAXC_CALL_STATE_FREE 0 /*!< Indicates a call slot is free */ #define IAXC_CALL_STATE_ACTIVE (1<<1) /*!< Indicates a call is active */ @@ -920,6 +922,26 @@ */ EXPORT int iaxc_get_netstats(int call, int *rtt, struct iaxc_netstat *local, struct iaxc_netstat *remote); +/*! + A structure containing information about a video capture device. +*/ +struct iaxc_video_device { + /*! + The "human readable" name of the device + */ + const char *name; + + /*! + unique id of the device + */ + const char *id_string; + + /*! + iaxclient id of the device + */ + int id; +}; + #define IAXC_AD_INPUT (1<<0) /*!< Device is usable for input*/ #define IAXC_AD_OUTPUT (1<<1) /*!< Device is usable for output */ #define IAXC_AD_RING (1<<2) /*!< Device is usable for ring */ @@ -1112,6 +1134,23 @@ */ EXPORT int iaxc_set_audio_prefs(unsigned int prefs); +/*! + Get video capture device information: + \param devs Returns an array of iaxc_video_device structures. + The array will will be valid as long as iaxc is initialized. + \param nDevs Returns the number of devices in the devs array + \param devId Returns the id of the currently selected video capture device + + \return -1 on error, 0 if no change to the device list, 1 if it's been updated + */ +EXPORT int iaxc_video_devices_get(struct iaxc_video_device **devs, int *nDevs, int *devId); + +/*! + Sets the current video capture device + \param devId The id of the device to use for video capture + */ +EXPORT int iaxc_video_device_set(int devId); + /* * Acceptable range for video rezolution */ Modified: branches/team/mihai/echocan/lib/slice.c =================================================================== --- branches/team/mihai/echocan/lib/slice.c 2007-10-31 17:31:21 UTC (rev 1250) +++ branches/team/mihai/echocan/lib/slice.c 2007-10-31 19:01:27 UTC (rev 1251) @@ -32,7 +32,7 @@ return 0; } -int slice(char *data, +int slice(const char *data, unsigned int size, struct slice_set_t *slice_set, struct slicer_context *sc @@ -93,7 +93,8 @@ dsc->frame_complete = 0; } -char * deslice(char *in, int inlen, int *outlen, struct deslicer_context *dsc) +char * +deslice(const char *in, int inlen, int *outlen, struct deslicer_context *dsc) { unsigned char frame_index, slice_index, num_slices, version; unsigned short source_id; Modified: branches/team/mihai/echocan/lib/slice.h =================================================================== --- branches/team/mihai/echocan/lib/slice.h 2007-10-31 17:31:21 UTC (rev 1250) +++ branches/team/mihai/echocan/lib/slice.h 2007-10-31 19:01:27 UTC (rev 1251) @@ -77,7 +77,7 @@ * sc - holds stream information such as source id and frame index * Returns 0 if completed successfully or a negative value if failure. */ -int slice(char *data, +int slice(const char *data, unsigned int size, struct slice_set_t *slice_set, struct slicer_context *sc @@ -103,6 +103,7 @@ * Returns a pointer to a buffer containing the completed frame and updates * outlen with the frame size if successful */ -char * deslice(char *in, int inlen, int *outlen, struct deslicer_context *dsc); +char * +deslice(const char *in, int inlen, int *outlen, struct deslicer_context *dsc); -#endif // __SLICE_H__ +#endif Modified: branches/team/mihai/echocan/lib/video.c =================================================================== --- branches/team/mihai/echocan/lib/video.c 2007-10-31 17:31:21 UTC (rev 1250) +++ branches/team/mihai/echocan/lib/video.c 2007-10-31 19:01:27 UTC (rev 1251) @@ -31,13 +31,16 @@ #include "codec_theora.h" #endif +#if defined(WIN32) +#define strdup _strdup +#endif + struct video_info { vidcap_state * vc; vidcap_sapi * sapi; vidcap_src * src; struct vidcap_sapi_info sapi_info; - struct vidcap_src_info src_info; struct vidcap_fmt_info fmt_info; /* these are the requested (post-scaling) dimensions */ @@ -63,6 +66,15 @@ int prefs; struct slicer_context * sc; + + /* these two struct arrays are correlated by index */ + struct vidcap_src_info * vc_src_info; + struct iaxc_video_device * devices; + MUTEX dev_list_lock; + + int device_count; + int selected_device_id; + int next_id; }; struct video_format_info @@ -492,6 +504,24 @@ */ } +static int video_device_notification_callback(vidcap_sapi *sapi, + void * user_context) +{ + iaxc_event evt; + + if ( sapi != vinfo.sapi ) + { + fprintf(stderr, "ERROR: wrong sapi in device notification\n"); + return -1; + } + + /* notify application that device list has been updated */ + evt.type = IAXC_EVENT_VIDCAP_DEVICE; + iaxci_post_event(evt); + + return 0; +} + static int capture_callback(vidcap_src * src, void * user_data, struct vidcap_capture_info * cap_info) { @@ -517,6 +547,8 @@ const char * source_buf = 0; int source_buf_size = 0; + iaxc_event evt; + int i; if ( cap_info->error_status ) @@ -524,6 +556,9 @@ fprintf(stderr, "vidcap capture error %d\n", cap_info->error_status); vinfo.capturing = 0; + + evt.type = IAXC_EVENT_VIDCAP_ERROR; + iaxci_post_event(evt); return -1; } @@ -732,30 +767,10 @@ }; static const int fourcc_list_len = sizeof(fourcc_list) / sizeof(int); - int i; static const int max_factor = 2; int scale_factor; + int i; - if ( !vinfo.src ) - { - /* Acquire the default source */ - if ( !(vinfo.src = vidcap_src_acquire(vinfo.sapi, 0)) ) - { - fprintf(stderr, "failed to acquire video source\n"); - return -1; - } - - if ( vidcap_src_info_get(vinfo.src, &vinfo.src_info) ) - { - fprintf(stderr, "failed to get video source info\n"); - return -1; - } - - fprintf(stderr, "acquired vidcap source %s (%s)\n", - vinfo.src_info.description, - vinfo.src_info.identifier); - } - vinfo.width = vfinfo.width; vinfo.height = vfinfo.height; vinfo.fmt_info.fps_numerator = vfinfo.framerate; @@ -878,6 +893,46 @@ return 0; } +static int ensure_acquired(int dev_id) +{ + int dev_num; + + if ( !vinfo.src ) + { + MUTEXLOCK(&vinfo.dev_list_lock); + + for ( dev_num = 0; dev_num < vinfo.device_count; dev_num++ ) + { + if ( vinfo.devices[dev_num].id == dev_id ) + break; + } + + if ( dev_num == vinfo.device_count ) + { + MUTEXUNLOCK(&vinfo.dev_list_lock); + fprintf(stderr, "invalid vidcap dev id: %d\n", dev_id); + return -1; + } + + if ( !(vinfo.src = vidcap_src_acquire(vinfo.sapi, + &vinfo.vc_src_info[dev_num])) ) + { + vinfo.src = 0; + MUTEXUNLOCK(&vinfo.dev_list_lock); + fprintf(stderr, "failed to acquire video source\n"); + return -1; + } + + fprintf(stderr, "acquired vidcap source %s (%s)\n", + vinfo.vc_src_info[dev_num].description, + vinfo.vc_src_info[dev_num].identifier); + + MUTEXUNLOCK(&vinfo.dev_list_lock); + } + + return 0; +} + EXPORT int iaxc_set_video_prefs(unsigned int prefs) { const unsigned int prefs_mask = @@ -888,9 +943,14 @@ IAXC_VIDEO_PREF_SEND_DISABLE | IAXC_VIDEO_PREF_RECV_RGB32 | IAXC_VIDEO_PREF_CAPTURE_DISABLE; + int ret; if ( prefs & ~prefs_mask ) + { + fprintf(stderr, "ERROR: unexpected video preference: 0x%0x\n", + prefs); return -1; + } vinfo.prefs = prefs; @@ -911,7 +971,15 @@ { if ( vidcap_src_capture_stop(vinfo.src) ) fprintf(stderr, "failed vidcap_src_capture_stop\n"); + vinfo.capturing = 0; + + if ( vinfo.src && vidcap_src_release(vinfo.src) ) + { + fprintf(stderr, "failed to release a video source\n"); + } + + vinfo.src = 0; } MUTEXUNLOCK(&vinfo.camera_lock); } @@ -920,17 +988,30 @@ MUTEXLOCK(&vinfo.camera_lock); if ( !vinfo.capturing ) { + if ( vinfo.selected_device_id < 0 ) + { + MUTEXUNLOCK(&vinfo.camera_lock); + return -1; + } + + if ( ensure_acquired(vinfo.selected_device_id) ) + { + MUTEXUNLOCK(&vinfo.camera_lock); + return -1; + } + if ( prepare_for_capture() ) { MUTEXUNLOCK(&vinfo.camera_lock); return -1; } - if ( vidcap_src_capture_start(vinfo.src, - capture_callback, 0) ) + if ( (ret = vidcap_src_capture_start(vinfo.src, + capture_callback, 0)) ) { MUTEXUNLOCK(&vinfo.camera_lock); - fprintf(stderr, "failed to start video capture\n"); + fprintf(stderr, "failed to start video capture: %d\n", + ret); return -1; } @@ -1231,10 +1312,230 @@ return 0; } +EXPORT int iaxc_video_devices_get(struct iaxc_video_device **devs, + int *num_devs, int *id_selected) +{ + int new_device_count; + int old_device_count; + struct vidcap_src_info *new_src_list; + struct vidcap_src_info *old_src_list; + struct iaxc_video_device *new_iaxc_dev_list; + struct iaxc_video_device *old_iaxc_dev_list; + int found_selected_device = 0; + int list_changed = 0; + int i, n; + + /* update libvidcap's device list */ + new_device_count = vidcap_src_list_update(vinfo.sapi); + if ( new_device_count != vinfo.device_count ) + list_changed = 1; + + if ( new_device_count < 0 ) + { + fprintf(stderr, "ERROR: failed getting updated vidcap device list: %d\n", + new_device_count); + return -1; + } + + new_src_list = (struct vidcap_src_info *)malloc(new_device_count * + sizeof(struct vidcap_src_info)); + if ( !new_src_list ) + { + fprintf(stderr, "ERROR: failed updated source allocation\n"); + return -1; + } + + new_iaxc_dev_list = (struct iaxc_video_device *)malloc( + new_device_count * sizeof(struct iaxc_video_device)); + if ( !new_iaxc_dev_list ) + { + free(new_src_list); + fprintf(stderr, "ERROR: failed source allocation update\n"); + return -1; + } + + /* get an updated libvidcap device list */ + if ( vidcap_src_list_get(vinfo.sapi, new_device_count, new_src_list) ) + { + fprintf(stderr, "ERROR: failed vidcap_srcList_get()\n"); + + free(new_src_list); + free(new_iaxc_dev_list); + return -1; + } + + /* build a new iaxclient video source list */ + found_selected_device = 0; + for ( n = 0; n < new_device_count; n++ ) + { + new_iaxc_dev_list[n].name = strdup(new_src_list[n].description); + new_iaxc_dev_list[n].id_string = strdup(new_src_list[n].identifier); + + /* this device may have been here all along + * Check if it has, and re-assign that device id + * else assign a new id + */ + for ( i = 0; i < vinfo.device_count; i++ ) + { + if ( !strcmp(new_iaxc_dev_list[n].name, vinfo.devices[i].name) ) + { + /*fprintf(stderr, "EXISTING DEVICE: %s - (id=%d) '%s'\n", + new_iaxc_dev_list[n].name, + vinfo.devices[i].id, + new_iaxc_dev_list[n].id_string); + */ + new_iaxc_dev_list[n].id = vinfo.devices[i].id; + + if ( vinfo.selected_device_id == new_iaxc_dev_list[n].id ) + found_selected_device = 1; + break; + } + } + if ( i == vinfo.device_count ) + { + new_iaxc_dev_list[n].id = vinfo.next_id++; + fprintf(stderr, "NEW DEVICE: %s - (id=%d) '%s'\n", + new_iaxc_dev_list[n].name, + new_iaxc_dev_list[n].id, + new_iaxc_dev_list[n].id_string); + + list_changed = 1; + } + } + + if ( !list_changed ) + { + /* Free new lists. Nothing's really changed */ + free(new_src_list); + for ( i = 0; i < new_device_count; i++ ) + { + free((void *)new_iaxc_dev_list[i].name); + free((void *)new_iaxc_dev_list[i].id_string); + } + free(new_iaxc_dev_list); + } + else + { + old_device_count = vinfo.device_count; + old_src_list = vinfo.vc_src_info; + old_iaxc_dev_list = vinfo.devices; + + /* Update iaxclient's device list info */ + /* Lock since other iaxclient funcs use these fields */ + MUTEXLOCK(&vinfo.dev_list_lock); + + vinfo.device_count = new_device_count; + vinfo.vc_src_info = new_src_list; + vinfo.devices = new_iaxc_dev_list; + + MUTEXUNLOCK(&vinfo.dev_list_lock); + + /* free old lists */ + free(old_src_list); + for ( i = 0; i < old_device_count; i++ ) + { + free((void *)old_iaxc_dev_list[i].name); + free((void *)old_iaxc_dev_list[i].id_string); + } + free(old_iaxc_dev_list); + } + + *devs = vinfo.devices; + *num_devs = vinfo.device_count; + *id_selected = found_selected_device ? vinfo.selected_device_id : -1; + + return list_changed; +} + +EXPORT int iaxc_video_device_set(int capture_dev_id) +{ + int ret = 0; + int dev_num = 0; + + MUTEXLOCK(&vinfo.camera_lock); + + if ( capture_dev_id == vinfo.selected_device_id ) + { + MUTEXUNLOCK(&vinfo.camera_lock); + return 0; + } + + if ( capture_dev_id < 0 ) + { + MUTEXUNLOCK(&vinfo.camera_lock); + fprintf(stderr, "invalid video device id ( < 0 )\n"); + return -1; + } + + MUTEXLOCK(&vinfo.dev_list_lock); + + for ( dev_num = 0; dev_num < vinfo.device_count; dev_num++ ) + { + if ( vinfo.devices[dev_num].id == capture_dev_id ) + break; + } + + if ( dev_num == vinfo.device_count ) + { + MUTEXUNLOCK(&vinfo.dev_list_lock); + MUTEXUNLOCK(&vinfo.camera_lock); + fprintf(stderr, "invalid video device id: %d\n", + capture_dev_id); + return -1; + } + + vinfo.selected_device_id = capture_dev_id; + + if ( vinfo.src && vidcap_src_release(vinfo.src) ) + { + fprintf(stderr, "failed to release video source\n"); + } + + vinfo.src = 0; + + MUTEXUNLOCK(&vinfo.dev_list_lock); + + if ( vinfo.capturing ) + { + if ( ensure_acquired(capture_dev_id) ) + { + MUTEXUNLOCK(&vinfo.camera_lock); + return -1; + } + + if ( prepare_for_capture() ) + { + MUTEXUNLOCK(&vinfo.camera_lock); + return -1; + } + + if ( (ret = vidcap_src_capture_start(vinfo.src, + capture_callback, 0)) ) + { + MUTEXUNLOCK(&vinfo.camera_lock); + fprintf(stderr, "failed to restart video capture: %d\n", ret); + return -1; + } + } + + MUTEXUNLOCK(&vinfo.camera_lock); + + return 0; +} + int video_initialize(void) { + int i; + const int starting_id = 50; + memset(&vinfo, 0, sizeof(vinfo)); + MUTEXINIT(&vinfo.camera_lock); + MUTEXINIT(&vinfo.dev_list_lock); + + vinfo.width = vfinfo.width; + vinfo.height = vfinfo.height; + if ( !(vinfo.vc = vidcap_initialize()) ) { fprintf(stderr, "ERROR: failed vidcap_initialize\n"); @@ -1257,23 +1558,89 @@ vinfo.sapi_info.description, vinfo.sapi_info.identifier); - /* TODO: Maybe we should reevaluate these defaults. Once could - * make an argument that reasonable users of iaxclient might - * not want video to be delivered as soon as they iaxc_initialize(). + vinfo.selected_device_id = -1; + + vinfo.device_count = vidcap_src_list_update(vinfo.sapi); + if ( vinfo.device_count < 0 ) + { + fprintf(stderr, + "ERROR: failed updating video capture devices list\n"); + goto bail; + } + + vinfo.vc_src_info = (struct vidcap_src_info *)malloc(vinfo.device_count * + sizeof(struct vidcap_src_info)); + if ( !vinfo.vc_src_info ) + { + fprintf(stderr, "ERROR: failed vinfo field allocations\n"); + goto bail; + } + + vinfo.devices = (struct iaxc_video_device *)malloc(vinfo.device_count * + sizeof(struct iaxc_video_device)); + if ( !vinfo.devices ) + { + fprintf(stderr, "ERROR: failed vinfo field allocation\n"); + free(vinfo.vc_src_info); + goto bail; + } + + if ( vidcap_src_list_get(vinfo.sapi, vinfo.device_count, + vinfo.vc_src_info) ) + { + fprintf(stderr, "ERROR: failed vidcap_src_list_get()\n"); + free(vinfo.vc_src_info); + free(vinfo.devices); + goto bail; + } + + /* build initial iaxclient video source list */ + for ( i = 0; i < vinfo.device_count; i++ ) + { + vinfo.devices[i].name = strdup(vinfo.vc_src_info[i].description); + vinfo.devices[i].id_string = strdup(vinfo.vc_src_info[i].identifier); + /* Let's be clear that the device id is not some + * base-zero index. Once plug-n-play is implemented, + * these ids may diverge as devices are added + * and removed. + */ + vinfo.devices[i].id = i + starting_id; + } + vinfo.next_id = vinfo.devices[vinfo.device_count - 1].id + 1; + + /* set default source - the first device */ + if ( vinfo.device_count ) + { + iaxc_video_device_set(vinfo.devices[0].id); + } + + /* setup device notification callback + * for device insertion and removal */ + if ( vidcap_srcs_notify(vinfo.sapi, &video_device_notification_callback, 0) ) + { + fprintf(stderr, "ERROR: failed vidcap_srcs_notify()\n"); + goto late_bail; + } + vinfo.prefs = IAXC_VIDEO_PREF_RECV_LOCAL_RAW | - IAXC_VIDEO_PREF_RECV_REMOTE_RAW; + IAXC_VIDEO_PREF_RECV_REMOTE_RAW | + IAXC_VIDEO_PREF_CAPTURE_DISABLE; - MUTEXINIT(&vinfo.camera_lock); + return 0; - /* We reset the existing video preferences to yield the side-effect - * of potentially starting or stopping the video capture. - */ - iaxc_set_video_prefs(vinfo.prefs); +late_bail: + free(vinfo.vc_src_info); - return 0; + for ( i = 0; i < vinfo.device_count; i++ ) + { + free((void *)vinfo.devices[i].name); + free((void *)vinfo.devices[i].id_string); + } + free(vinfo.devices); + bail: vidcap_destroy(vinfo.vc); vinfo.vc = 0; @@ -1289,6 +1656,7 @@ vinfo.vc = 0; MUTEXDESTROY(&vinfo.camera_lock); + MUTEXDESTROY(&vinfo.dev_list_lock); if ( vinfo.converted_i420_buf ) { @@ -1324,7 +1692,7 @@ * we are saying that the "camera is working" if there exists * more than zero cameras. */ - return vidcap_src_list_update(vinfo.sapi); + return vidcap_src_list_update(vinfo.sapi) > 0; } int video_send_stats(struct iaxc_call * call) Modified: branches/team/mihai/echocan/simpleclient/stresstest/stresstest.c =================================================================== --- branches/team/mihai/echocan/simpleclient/stresstest/stresstest.c 2007-10-31 17:31:21 UTC (rev 1250) +++ branches/team/mihai/echocan/simpleclient/stresstest/stresstest.c 2007-10-31 19:01:27 UTC (rev 1251) @@ -23,7 +23,6 @@ #include <signal.h> #include "iaxclient.h" -#include "slice.h" #include "file.h" #ifdef WIN32 @@ -57,7 +56,8 @@ static int send_video = 1; static int send_audio = 1; static int print_netstats = 0; -static int timeout = 0; +static int call_timeout_ms = 0; +static int connect_timeout_ms = 5000; static int video_frames_count = 0; static int audio_frames_count = 0; @@ -193,7 +193,8 @@ " -a stop sending audio\n" " -l run file in a loop\n" " -n dump periodic netstats to log file\n" - " -t <timeout> terminate after timeout seconds and report status via return code\n" + " -t <TIMEOUT> terminate call after TIMEOUT seconds\n" + " -c <TIMEOUT> try connecting for TIMEOUT seconds (default 5)\n" " -L <FILE> log to FILE\n" "\n" ); @@ -269,14 +270,14 @@ switch ( argv[i][1] ) { case 'F': /* set video params */ - { - formatp = 1 << atoi(argv[++i]); - framerate = atoi(argv[++i]); - bitrate = atoi(argv[++i]); - width = atoi(argv[++i]); - height = atoi(argv[++i]); - fragsize = atoi(argv[++i]); - } + if ( i+6 >= argc ) + usage(); + formatp = 1 << atoi(argv[++i]); + framerate = atoi(argv[++i]); + bitrate = atoi(argv[++i]); + width = atoi(argv[++i]); + height = atoi(argv[++i]); + fragsize = atoi(argv[++i]); break; case 'o': if ( i+1 >= argc ) @@ -298,8 +299,13 @@ case 't': if ( i+1 >= argc ) usage(); - timeout = 1000 * atoi(argv[++i]); + call_timeout_ms = 1000 * atoi(argv[++i]); break; + case 'c': + if ( i+1 >= argc ) + usage(); + connect_timeout_ms = 1000 * atoi(argv[++i]); + break; case 'L': if ( i+1 >= argc ) usage(); @@ -314,7 +320,7 @@ usage(); } } else - dest=argv[i]; + dest = argv[i]; } if ( dest == NULL ) @@ -355,11 +361,12 @@ mylog("Failed to make call to '%s'", dest); // Wait for the call to be established; - while ( !call_established ) + while ( !call_established && running ) { struct timeval now; gettimeofday(&now, NULL); - if ( timeout > 0 && msecdiff(&start_time, &now) > timeout ) + if ( connect_timeout_ms > 0 && + msecdiff(&start_time, &now) > connect_timeout_ms ) hangup_and_exit(TEST_NO_CONNECTION); iaxc_millisleep(5); } @@ -394,7 +401,8 @@ // Exit after a positive timeout gettimeofday(&now, NULL); - if ( timeout > 0 && msecdiff(&start_time, &now) > timeout ) + if ( call_timeout_ms > 0 && + msecdiff(&start_time, &now) > call_timeout_ms ) running = 0; } Modified: branches/team/mihai/echocan/simpleclient/vtestcall/vtestcall.c =================================================================== --- branches/team/mihai/echocan/simpleclient/vtestcall/vtestcall.c 2007-10-31 17:31:21 UTC (rev 1250) +++ branches/team/mihai/echocan/simpleclient/vtestcall/vtestcall.c 2007-10-31 19:01:27 UTC (rev 1251) @@ -238,6 +238,9 @@ e.ev.audio.source == IAXC_SOURCE_REMOTE ? "remote" : "local", e.ev.audio.encoded ? "encoded" : "raw"); break; + case IAXC_EVENT_VIDCAP_ERROR: + fprintf(stderr, "\nVIDEO CAPTURE DEVICE ERROR\n"); + break; default: break; } @@ -275,12 +278,28 @@ int nDevs, input, output,ring; int i; + int vinput; + int nVdevs; + struct iaxc_video_device *vDevs; + iaxc_audio_devices_get(&devs,&nDevs, &input, &output, &ring); + printf("\nThere are %d audio devices:\n", nDevs); for(i=0;i<nDevs;i++) { - fprintf(stderr, "DEVICE ID=%d NAME=%s CAPS=%lx\n", devs[i].devID, devs[i].name, devs[i].capabilities); + fprintf(stderr, "AUDIO DEVICE ID = %d NAME = %s CAPS=%lx\n", + devs[i].devID, devs[i].name, devs[i].capabilities); iaxc_audio_devices_set(input,output,ring); } + + iaxc_video_devices_get(&vDevs, &nVdevs, &vinput); + printf("\nThere are %d video capture devices:\n", nVdevs); + for ( i = 0; i < nVdevs; i++ ) + { + printf("VIDEO DEVICE ID = %d NAME = %s\n", + vDevs[i].id, vDevs[i].name); + } + printf("Currently selected VIDEO device id: %d\n", vinput); + } void usage() @@ -363,7 +382,11 @@ exit(-1); } - if ( v.size <= 0 ) fprintf(stderr, "WARNING: size %d in callback\n", v.size); + if ( v.size <= 0 ) + { + fprintf(stderr, "WARNING: size %d in callback\n", v.size); + return 0; + } if ( !remote ) { @@ -532,12 +555,18 @@ //iaxc_set_audio_prefs(IAXC_AUDIO_PREF_RECV_LOCAL_RAW | IAXC_AUDIO_PREF_RECV_REMOTE_RAW); fprintf(f, "\n\ - TestCall accept some keyboard input while it's running.\n\ + vtestcall accepts keyboard input while it's running.\n\ You must hit 'enter' for your keypresses to be recognized,\n\ - although you can type more than one key on a line\n\ + although you can type more than one key on a line:\n\ \n\ - q: drop the call and hangup.\n\ - 0-9 * or #: dial those DTMF digits.\n"); + s: switch video capture devices \n\ + b: bypass video jitter stuff\n\ + r: reject incoming call\n\ + d: dial\n\ + c: set caller id info\n\ + w: video window toggle\n\ + 0-9 * or #: dial those DTMF digits\n\ + q: drop the call and hangup\n"); printf("Starting processing thread...\n"); iaxc_start_processing_thread(); @@ -619,6 +648,39 @@ iaxc_set_callerid(myCIDname,myCIDnumber); } break; + case SDLK_s: + { + int input; + int ndevs; + struct iaxc_video_device *vDevs; + int newVideoDevId; + + iaxc_video_devices_get(&vDevs, &ndevs, &input); + + printf("There are %d video capture devices:\n", ndevs); + for ( i = 0; i < ndevs; i++ ) + { + printf("VIDEO DEVICE ID = %d NAME = %s\n", vDevs[i].id, vDevs[i].name); + } + printf("Currently selected device id: %d\n", input); + + printf("Select video capture device: "); + fflush(stdin); + fscanf(stdin,"%d", &newVideoDevId); + + if ( iaxc_video_device_set(newVideoDevId) ) + { + printf("Error selecting device id %d\n", + newVideoDevId); + break; + } + + /* explicitly set the prefs again in case + * previous capture device has failed + */ + iaxc_set_video_prefs( iaxc_get_video_prefs() ); + } + break; case SDLK_t: /* transmit-only */ printf("transmit mode active\n"); break; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |