diff --git a/.gitignore b/.gitignore
index e288273..64f5a8f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,14 @@
+.metadata
+RemoteSystemsTempFiles
+
*/gen/
*/libs/
*/obj/
+*/.settings
!*/bin/
*/bin/*
!*/bin/*.apk
+
+CamSvcSrv/jni/Upgrade.bat
+OpenCV-android-sdk
diff --git a/CamSvcSrv/.classpath b/CamSvcSrv/.classpath
index 7bc01d9..5176974 100644
--- a/CamSvcSrv/.classpath
+++ b/CamSvcSrv/.classpath
@@ -1,9 +1,9 @@
-
-
+
+
diff --git a/CamSvcSrv/bin/CamSvcSrv.apk b/CamSvcSrv/bin/CamSvcSrv.apk
index 98ca126..89254e7 100644
Binary files a/CamSvcSrv/bin/CamSvcSrv.apk and b/CamSvcSrv/bin/CamSvcSrv.apk differ
diff --git a/CamSvcSrv/jni/Android.mk b/CamSvcSrv/jni/Android.mk
index ff5c2a5..beb8012 100644
--- a/CamSvcSrv/jni/Android.mk
+++ b/CamSvcSrv/jni/Android.mk
@@ -6,15 +6,15 @@ OPENCV_LIB_TYPE := STATIC
OPENCV_INSTALL_MODULES := on
OPENCV_CAMERA_MODULES := on
-OPENCV_MK_PATH := ..\OpenCV-2.4.9-android-sdk\sdk\native\jni
+OPENCV_MK_PATH := ..\OpenCV-android-sdk\sdk\native\jni
include $(OPENCV_MK_PATH)/OpenCV.mk
LOCAL_MODULE := appnativecpp_opencv_jni
-LOCAL_SRC_FILES := appnative.cpp Main.c Globals.c OSNet.c OSCriticalSection.c OSThread.c OSMisc.c OSTime.c OSCore.c
+LOCAL_SRC_FILES := appnative.cpp Main.cpp Globals.cpp OSNet.c OSCriticalSection.c OSThread.c OSMisc.c OSTime.c OSCore.c
LOCAL_LDLIBS += -llog -ldl
# -x c++ because of OpenCV...
-LOCAL_CFLAGS += -Wall -Wextra -DDISABLE_GUI_REMOTEWEBCAMMULTISRV -DDISABLE_TIMER_RECORDING -DOPENCV249 -x c++
+LOCAL_CFLAGS += -Wall -Wextra -D DISABLE_GUI_REMOTEWEBCAMMULTISRV -D DISABLE_TIMER_RECORDING -D DISABLE_CUSTOM_BAUDRATE -D USE_OPENCV_HIGHGUI_CPP_API -x c++
include $(BUILD_SHARED_LIBRARY)
diff --git a/CamSvcSrv/jni/CvCore.c b/CamSvcSrv/jni/CvCore.c
deleted file mode 100644
index cba893b..0000000
--- a/CamSvcSrv/jni/CvCore.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/***************************************************************************************************************:')
-
-CvCore.c
-
-IplImage data handling.
-2 types of IplImage format should be used in the functions :
-_ a default RGB color format than can be created using CreateDefaultColorCvImg() or cvLoadImage("file.ppm", 1).
-_ a default gray format than can be created using CreateDefaultGrayCvImg() or cvLoadImage("file.pgm", 0).
-Note that you can use most of the OpenCV functions with such IplImage formats.
-
-Fabrice Le Bars
-
-Created : 2009-03-26
-
-***************************************************************************************************************:)*/
-
-#include "CvCore.h"
diff --git a/CamSvcSrv/jni/CvCore.h b/CamSvcSrv/jni/CvCore.h
deleted file mode 100644
index 26c24a9..0000000
--- a/CamSvcSrv/jni/CvCore.h
+++ /dev/null
@@ -1,598 +0,0 @@
-/***************************************************************************************************************:')
-
-CvCore.h
-
-IplImage data handling.
-2 types of IplImage format should be used in the functions :
-_ a default RGB color format than can be created using CreateDefaultColorCvImg() or cvLoadImage("file.ppm", 1).
-_ a default gray format than can be created using CreateDefaultGrayCvImg() or cvLoadImage("file.pgm", 0).
-Note that you can use most of the OpenCV functions with such IplImage formats.
-
-Fabrice Le Bars
-
-Created : 2009-03-26
-
-***************************************************************************************************************:)*/
-
-// Prevent Visual Studio Intellisense from defining _WIN32 and _MSC_VER when we use
-// Visual Studio to edit Linux or Borland C++ code.
-#ifdef __linux__
-# undef _WIN32
-#endif // __linux__
-#if defined(__GNUC__) || defined(__BORLANDC__)
-# undef _MSC_VER
-#endif // defined(__GNUC__) || defined(__BORLANDC__)
-
-#ifndef CVCORE_H
-#define CVCORE_H
-
-#include "OSTime.h"
-
-#ifdef _MSC_VER
-// Disable some Visual Studio warnings.
-#pragma warning(disable : 4100)
-#pragma warning(disable : 4458)
-#pragma warning(disable : 4996)
-#pragma warning(disable : 6204)
-#pragma warning(disable : 6201)
-#pragma warning(disable : 6294)
-#pragma warning(disable : 6385)
-#endif // _MSC_VER
-
-#ifdef __BORLANDC__
-// Disable some Borland C++ Builder warnings.
-#pragma warn -8019
-#endif // __BORLANDC__
-
-#ifdef __GNUC__
-// Disable some GCC warnings.
-//#pragma GCC diagnostic ignored "-Wunused-parameter"
-//#pragma GCC diagnostic ignored "-Wunused-variable"
-//#pragma GCC diagnostic ignored "-Wunused-value"
-#pragma GCC diagnostic ignored "-Wunused-function"
-//#pragma GCC diagnostic ignored "-Wunused"
-//#pragma GCC diagnostic ignored "-Wcomment"
-//#pragma GCC diagnostic ignored "-Wuninitialized"
-//#pragma GCC diagnostic ignored "-Wunknown-pragmas"
-#if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
-#pragma GCC diagnostic push
-#endif // (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
-#endif // __GNUC__
-
-// OpenCV headers.
-#if defined(OPENCV220) || defined(OPENCV231) || defined(OPENCV242) || defined(OPENCV249) || defined(OPENCV2413) || defined(OPENCV310)
-// min and max might cause incompatibilities...
-#if !defined(DISABLE_MINMAX_UNDEFINITION)
-#ifdef max
-#undef max
-#endif // max
-#ifdef min
-#undef min
-#endif // min
-#endif // !defined(DISABLE_MINMAX_UNDEFINITION)
-// To try to solve cvRound() undefined problem in C mode in OpenCV 3.1.0...
-#if defined(OPENCV310)
-#include "opencv2/core/fast_math.hpp"
-#endif // defined(OPENCV310)
-//#include "opencv/cv.h" // Sometimes cause strange errors in debug and C++ mode due to the redefinition of free()...
-//#include "opencv/cvwimage.h"
-//#include "opencv/cxcore.h"
-//#include "opencv/highgui.h"
-#include "opencv2/core/core_c.h"
-#include "opencv2/imgproc/imgproc_c.h"
-#include "opencv2/highgui/highgui_c.h"
-// The 3 following headers do not build in C mode.
-#ifdef __cplusplus
-#include "opencv/cvaux.h"
-//#include "opencv/cxmisc.h"
-//#include "opencv/ml.h"
-#include "opencv2/core/core.hpp"
-#include "opencv2/imgproc/imgproc.hpp"
-#include "opencv2/highgui/highgui.hpp"
-//#include "opencv2/contrib/contrib.hpp"
-#endif // __cplusplus
-// min and max may be undefined so we need to redefine them here...
-#if !defined(DISABLE_MINMAX_REDEFINITION)
-#if !defined(NOMINMAX) || defined(FORCE_MINMAX_DEFINITION)
-#ifndef max
-#define max(a,b) (((a) > (b)) ? (a) : (b))
-#endif // max
-#ifndef min
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#endif // min
-#endif // !defined(NOMINMAX) || defined(FORCE_MINMAX_DEFINITION)
-#endif // !defined(DISABLE_MINMAX_REDEFINITION)
-#else
-#include "cv.h"
-#include "cvaux.h"
-#include "highgui.h"
-#endif // defined(OPENCV220) || defined(OPENCV231) || defined(OPENCV242) || defined(OPENCV249) || defined(OPENCV2413) || defined(OPENCV310)
-
-#ifdef __GNUC__
-// Restore the GCC warnings previously disabled.
-#if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
-#pragma GCC diagnostic pop
-#else
-//#pragma GCC diagnostic warning "-Wunknown-pragmas"
-//#pragma GCC diagnostic warning "-Wuninitialized"
-//#pragma GCC diagnostic warning "-Wcomment"
-//#pragma GCC diagnostic warning "-Wunused"
-#pragma GCC diagnostic warning "-Wunused-function"
-//#pragma GCC diagnostic warning "-Wunused-value"
-//#pragma GCC diagnostic warning "-Wunused-variable"
-//#pragma GCC diagnostic warning "-Wunused-parameter"
-#endif // (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
-#endif // __GNUC__
-
-#ifdef __BORLANDC__
-// Restore the Borland C++ Builder warnings previously disabled.
-#pragma warn .8019
-#endif // __BORLANDC__
-
-#ifdef _MSC_VER
-// Restore the Visual Studio warnings previously disabled.
-#pragma warning(default : 6385)
-#pragma warning(default : 6294)
-#pragma warning(default : 6201)
-#pragma warning(default : 6204)
-#pragma warning(default : 4996)
-#pragma warning(default : 4458)
-#pragma warning(default : 4100)
-#endif // _MSC_VER
-
-/*
-Create and initialize an IplImage with a simple default color format.
-Use DestroyDefaultColorCvImg() or cvReleaseImage() to free the picture data at
-the end.
-See the documentation of OpenCV for more information.
-
-IplImage** ppImg : (INOUT) Valid pointer to the pointer to the structure.
-UINT width : (IN) Width of the picture (in pixels).
-UINT height : (IN) Height of the picture (in pixels).
-
-Return : EXIT_SUCCESS or EXIT_FAILURE if there is an error.
-*/
-inline int CreateDefaultColorCvImg(IplImage** ppImg, UINT width, UINT height)
-{
- *ppImg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
-
- if (*ppImg == NULL)
- {
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
-
-/*
-Create and initialize a structure that is a copy of an IplImage.
-Use DestroyDefaultColorCvImg() or cvReleaseImage() to free pDataDest at the
-end.
-See the documentation of OpenCV for more information.
-
-IplImage** ppImgDest : (INOUT) Valid pointer to the pointer to the structure
-that will receive the copy of pImgSrc.
-IplImage* pImgSrc : (IN) Pointer to the IplImage to copy.
-Note that depending on how it was created, it must or must not be destroyed by
-DestroyDefaultColorCvImg() or cvReleaseImage().
-BOOL bOnlyCopyData : (IN) TRUE if pDataDest corresponds already to an IplImage
-structure with the same characteristics as pDataSrc, FALSE if it must be
-entirely initialized.
-
-Return : EXIT_SUCCESS or EXIT_FAILURE if there is an error.
-*/
-inline int CopyDefaultColorCvImg(IplImage** ppImgDest, IplImage* pImgSrc, BOOL bOnlyCopyData)
-{
- if (bOnlyCopyData)
- {
- cvCopy(pImgSrc, *ppImgDest, 0);
-
- if (*ppImgDest == NULL)
- {
- return EXIT_FAILURE;
- }
- }
- else
- {
- *ppImgDest = cvCloneImage(pImgSrc);
-
- if (*ppImgDest == NULL)
- {
- return EXIT_FAILURE;
- }
- }
-
- return EXIT_SUCCESS;
-}
-
-/*
-Create and initialize an IplImage with a simple default gray format.
-Use DestroyDefaultGrayCvImg() or cvReleaseImage() to free the picture data at
-the end.
-See the documentation of OpenCV for more information.
-
-IplImage** ppImg : (INOUT) Valid pointer to the pointer to the structure.
-UINT width : (IN) Width of the picture (in pixels).
-UINT height : (IN) Height of the picture (in pixels).
-
-Return : EXIT_SUCCESS or EXIT_FAILURE if there is an error.
-*/
-inline int CreateDefaultGrayCvImg(IplImage** ppImg, UINT width, UINT height)
-{
- *ppImg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-
- if (*ppImg == NULL)
- {
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
-
-/*
-Create and initialize a structure that is a copy of an IplImage.
-Use DestroyDefaultGrayCvImg() or cvReleaseImage() to free pDataDest at the
-end.
-See the documentation of OpenCV for more information.
-
-IplImage** ppImgDest : (INOUT) Valid pointer to the pointer to the structure
-that will receive the copy of pImgSrc.
-IplImage* pImgSrc : (IN) Pointer to the IplImage to copy.
-Note that depending on how it was created, it must or must not be destroyed by
-DestroyDefaultGrayCvImg() or cvReleaseImage().
-BOOL bOnlyCopyData : (IN) TRUE if pDataDest corresponds already to an IplImage
-structure with the same characteristics as pDataSrc, FALSE if it must be
-entirely initialized.
-
-Return : EXIT_SUCCESS or EXIT_FAILURE if there is an error.
-*/
-inline int CopyDefaultGrayCvImg(IplImage** ppImgDest, IplImage* pImgSrc, BOOL bOnlyCopyData)
-{
- if (bOnlyCopyData)
- {
- cvCopy(pImgSrc, *ppImgDest, 0);
-
- if (*ppImgDest == NULL)
- {
- return EXIT_FAILURE;
- }
- }
- else
- {
- *ppImgDest = cvCloneImage(pImgSrc);
-
- if (*ppImgDest == NULL)
- {
- return EXIT_FAILURE;
- }
- }
-
- return EXIT_SUCCESS;
-}
-
-/*
-Destroy an IplImage created with CreateDefaultColorCvImg() or
-CreateDefaultColorCvImgFromFile(). Note that it is only a call to cvReleaseImage().
-See the documentation of OpenCV for more information.
-
-IplImage** ppImg : (INOUT) Valid pointer to the pointer to the structure.
-
-Return : EXIT_SUCCESS or EXIT_FAILURE if there is an error.
-*/
-inline int DestroyDefaultColorCvImg(IplImage** ppImg)
-{
- cvReleaseImage(ppImg);
-
- return EXIT_SUCCESS;
-}
-
-/*
-Destroy an IplImage created with CreateDefaultGrayCvImg() or
-CreateDefaultGrayCvImgFromFile(). Note that it is only a call to cvReleaseImage().
-See the documentation of OpenCV for more information.
-
-IplImage** ppImg : (INOUT) Valid pointer to the pointer to the structure.
-
-Return : EXIT_SUCCESS or EXIT_FAILURE if there is an error.
-*/
-inline int DestroyDefaultGrayCvImg(IplImage** ppImg)
-{
- cvReleaseImage(ppImg);
-
- return EXIT_SUCCESS;
-}
-
-/*
-Get the color of the pixel at line i and row j of a color IplImage.
-The function does not check any parameter.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-UCHAR* pRed : (INOUT) Pointer to the red value of the pixel.
-UCHAR* pGreen : (INOUT) Pointer to the green value of the pixel.
-UCHAR* pBlue : (INOUT) Pointer to the blue value of the pixel.
-
-Return : Nothing.
-*/
-inline void GetDefaultColorCvImgPixelQuick(IplImage* pImg, UINT i, UINT j, UCHAR* pRed, UCHAR* pGreen, UCHAR* pBlue)
-{
- int index = 3*(j+pImg->width*i);
-
- *pRed = pImg->imageData[index+2];
- *pGreen = pImg->imageData[index+1];
- *pBlue = pImg->imageData[index];
-}
-
-/*
-Get the color of the pixel at line i and row j of a color IplImage.
-The function handles automatically any out of bounds index.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-int i : (IN) Line of the pixel.
-int j : (IN) Row of the pixel.
-UCHAR* pRed : (INOUT) Pointer to the red value of the pixel.
-UCHAR* pGreen : (INOUT) Pointer to the green value of the pixel.
-UCHAR* pBlue : (INOUT) Pointer to the blue value of the pixel.
-
-Return : Nothing.
-*/
-inline void GetDefaultColorCvImgPixel(IplImage* pImg, int i, int j, UCHAR* pRed, UCHAR* pGreen, UCHAR* pBlue)
-{
- int index;
-
- //i = min(max(i, 0), (int)pImg->height-1);
- //j = min(max(j, 0), (int)pImg->width-1);
-
- if ((i < 0)||(i >= (int)pImg->height)||(j < 0)||(j >= (int)pImg->width))
- {
- return;
- }
-
- index = 3*(j+pImg->width*i);
-
- *pRed = pImg->imageData[index+2];
- *pGreen = pImg->imageData[index+1];
- *pBlue = pImg->imageData[index];
-}
-
-/*
-Set the color of the pixel at line i and row j of a color IplImage.
-The function does not check any parameter.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-UCHAR red : (IN) New red value of the pixel (between 0 and 255).
-UCHAR green : (IN) New green value of the pixel (between 0 and 255).
-UCHAR blue : (IN) New blue value of the pixel (between 0 and 255).
-
-Return : Nothing.
-*/
-inline void SetDefaultColorCvImgPixelQuick(IplImage* pImg, UINT i, UINT j, UCHAR red, UCHAR green, UCHAR blue)
-{
- int index = 3*(j+pImg->width*i);
-
- pImg->imageData[index+2] = red;
- pImg->imageData[index+1] = green;
- pImg->imageData[index] = blue;
-}
-
-/*
-Set the pixel at line i and row j of a color IplImage.
-The function handles automatically any out of bounds index.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-int i : (IN) Line of the pixel.
-int j : (IN) Row of the pixel.
-UCHAR red : (IN) New red value of the pixel (between 0 and 255).
-UCHAR green : (IN) New green value of the pixel (between 0 and 255).
-UCHAR blue : (IN) New blue value of the pixel (between 0 and 255).
-
-Return : Nothing.
-*/
-inline void SetDefaultColorCvImgPixel(IplImage* pImg, int i, int j, UCHAR red, UCHAR green, UCHAR blue)
-{
- int index;
-
- //i = min(max(i, 0), (int)pImg->height-1);
- //j = min(max(j, 0), (int)pImg->width-1);
-
- if ((i < 0)||(i >= (int)pImg->height)||(j < 0)||(j >= (int)pImg->width))
- {
- return;
- }
-
- index = 3*(j+pImg->width*i);
-
- pImg->imageData[index+2] = red;
- pImg->imageData[index+1] = green;
- pImg->imageData[index] = blue;
-}
-
-/*
-Get the red value of the pixel at line i and row j of a color IplImage.
-The function does not check any parameter.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-
-Return : The red value (between 0 and 255).
-*/
-inline UCHAR GetDefaultColorCvImgPixelR(IplImage* pImg, UINT i, UINT j)
-{
- return pImg->imageData[3*(j+pImg->width*i)+2];
-}
-
-/*
-Get the green value of the pixel at line i and row j of a color IplImage.
-The function does not check any parameter.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-
-Return : The green value (between 0 and 255).
-*/
-inline UCHAR GetDefaultColorCvImgPixelG(IplImage* pImg, UINT i, UINT j)
-{
- return pImg->imageData[3*(j+pImg->width*i)+1];
-}
-
-/*
-Get the blue value of the pixel at line i and row j of a color IplImage.
-The function does not check any parameter.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-
-Return : The blue value (between 0 and 255).
-*/
-inline UCHAR GetDefaultColorCvImgPixelB(IplImage* pImg, UINT i, UINT j)
-{
- return pImg->imageData[3*(j+pImg->width*i)];
-}
-
-/*
-Set the red value of the pixel at line i and row j of a color IplImage.
-The function does not check any parameter.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-UCHAR red : (IN) New red value (between 0 and 255).
-
-Return : Nothing.
-*/
-inline void SetDefaultColorCvImgPixelR(IplImage* pImg, UINT i, UINT j, UCHAR red)
-{
- pImg->imageData[3*(j+pImg->width*i)+2] = red;
-}
-
-/*
-Set the green value of the pixel at line i and row j of a color IplImage.
-The function does not check any parameter.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-UCHAR red : (IN) New green value (between 0 and 255).
-
-Return : Nothing.
-*/
-inline void SetDefaultColorCvImgPixelG(IplImage* pImg, UINT i, UINT j, UCHAR green)
-{
- pImg->imageData[3*(j+pImg->width*i)+1] = green;
-}
-
-/*
-Set the blue value of the pixel at line i and row j of a color IplImage.
-The function does not check any parameter.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-UCHAR red : (IN) New blue value (between 0 and 255).
-
-Return : Nothing.
-*/
-inline void SetDefaultColorCvImgPixelB(IplImage* pImg, UINT i, UINT j, UCHAR blue)
-{
- pImg->imageData[3*(j+pImg->width*i)] = blue;
-}
-
-/*
-Get the gray value of the pixel at line i and row j of a gray IplImage.
-The function does not check any parameter.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-
-Return : The gray value (between 0 and 255).
-*/
-inline UCHAR GetDefaultGrayCvImgPixelQuick(IplImage* pImg, UINT i, UINT j)
-{
- return pImg->imageData[j+pImg->width*i];
-}
-
-/*
-Get the gray value of the pixel at line i and row j of a gray IplImage.
-The function handles automatically any out of bounds index.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-
-Return : The gray value (between 0 and 255).
-*/
-inline UCHAR GetDefaultGrayCvImgPixel(IplImage* pImg, int i, int j)
-{
- //i = min(max(i, 0), (int)pImg->height-1);
- //j = min(max(j, 0), (int)pImg->width-1);
-
- if ((i < 0)||(i >= (int)pImg->height)||(j < 0)||(j >= (int)pImg->width))
- {
- return 0;
- }
-
- return pImg->imageData[j+pImg->width*i];
-}
-
-/*
-Set the gray value of the pixel at line i and row j of a gray IplImage.
-The function does not check any parameter.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-UCHAR value : (IN) New gray value (between 0 and 255).
-
-Return : Nothing.
-*/
-inline void SetDefaultGrayCvImgPixelQuick(IplImage* pImg, UINT i, UINT j, UCHAR value)
-{
- pImg->imageData[j+pImg->width*i] = value;
-}
-
-/*
-Set the gray value of the pixel at line i and row j of a gray IplImage.
-The function handles automatically any out of bounds index.
-See the documentation of OpenCV for more information.
-
-IplImage* pImg : (IN) Pointer to the structure.
-UINT i : (IN) Line of the pixel.
-UINT j : (IN) Row of the pixel.
-UCHAR value : (IN) New gray value (between 0 and 255).
-
-Return : Nothing.
-*/
-inline void SetDefaultGrayCvImgPixel(IplImage* pImg, int i, int j, UCHAR value)
-{
- //i = min(max(i, 0), (int)pImg->height-1);
- //j = min(max(j, 0), (int)pImg->width-1);
-
- if ((i < 0)||(i >= (int)pImg->height)||(j < 0)||(j >= (int)pImg->width))
- {
- return;
- }
-
- pImg->imageData[j+pImg->width*i] = value;
-}
-
-#endif // CVCORE_H
diff --git a/CamSvcSrv/jni/CvInc.h b/CamSvcSrv/jni/CvInc.h
new file mode 100644
index 0000000..feb8965
--- /dev/null
+++ b/CamSvcSrv/jni/CvInc.h
@@ -0,0 +1,220 @@
+/***************************************************************************************************************:')
+
+CvInc.h
+
+Fabrice Le Bars
+
+Created : 2018-08-07
+
+***************************************************************************************************************:)*/
+
+// Prevent Visual Studio Intellisense from defining _WIN32 and _MSC_VER when we use
+// Visual Studio to edit Linux or Borland C++ code.
+#ifdef __linux__
+# undef _WIN32
+#endif // __linux__
+#if defined(__GNUC__) || defined(__BORLANDC__)
+# undef _MSC_VER
+#endif // defined(__GNUC__) || defined(__BORLANDC__)
+
+#ifndef CVINC_H
+#define CVINC_H
+
+#ifdef _MSC_VER
+// Disable some Visual Studio warnings.
+#pragma warning(disable : 4100)
+#pragma warning(disable : 4458)
+#pragma warning(disable : 4996)
+#pragma warning(disable : 6204)
+#pragma warning(disable : 6201)
+#pragma warning(disable : 6294)
+#pragma warning(disable : 6385)
+#endif // _MSC_VER
+
+#ifdef __BORLANDC__
+// Disable some Borland C++ Builder warnings.
+#pragma warn -8019
+#endif // __BORLANDC__
+
+#ifdef __GNUC__
+// Disable some GCC warnings.
+#if (__GNUC__ >= 9)
+#pragma GCC diagnostic ignored "-Wdeprecated-copy"
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#endif // (__GNUC__ >= 9)
+//#pragma GCC diagnostic ignored "-Wunused-parameter"
+//#pragma GCC diagnostic ignored "-Wunused-variable"
+//#pragma GCC diagnostic ignored "-Wunused-value"
+#pragma GCC diagnostic ignored "-Wunused-function"
+//#pragma GCC diagnostic ignored "-Wunused"
+//#pragma GCC diagnostic ignored "-Wcomment"
+//#pragma GCC diagnostic ignored "-Wuninitialized"
+//#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
+#pragma GCC diagnostic push
+#endif // (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
+#endif // __GNUC__
+
+// OpenCV headers.
+#ifndef DISABLE_OPENCV_VERSION
+// This header should only contain simple C code without dependencies on other headers...
+#include "opencv2/core/version.hpp"
+#else
+// OpenCV 1.X.X...
+#include "cv.h"
+#include "cvaux.h"
+#include "highgui.h"
+#endif // !DISABLE_OPENCV_VERSION
+
+// Temporary workaround because many conversions from C to C++ types are disabled by default after OpenCV 4.2.0...
+#ifndef DISABLE_OPENCV_C_API_CTORS
+#if (CV_MAJOR_VERSION >= 4)
+#if (CV_MINOR_VERSION >= 2)
+#ifndef CV__ENABLE_C_API_CTORS
+#define CV__ENABLE_C_API_CTORS
+#endif // !CV__ENABLE_C_API_CTORS
+#ifndef CV__SKIP_MESSAGE_MALFORMED_C_API_CTORS
+#define CV__SKIP_MESSAGE_MALFORMED_C_API_CTORS
+#endif // !CV__SKIP_MESSAGE_MALFORMED_C_API_CTORS
+#endif // (CV_MINOR_VERSION >= 2)
+#endif // (CV_MAJOR_VERSION >= 4)
+#endif // !DISABLE_OPENCV_C_API_CTORS
+
+#if (CV_MAJOR_VERSION >= 2)
+// To try to solve cvRound() undefined problem in C mode in OpenCV 3.1.0...
+// After OpenCV 3.2.0, C mode will probably not build any more due to several problems in core OpenCV headers...
+// Starting with OpenCV 4.0.0, most of the C headers have been removed...
+#if (CV_MAJOR_VERSION == 3)
+#include "opencv2/core/fast_math.hpp"
+#endif // (CV_MAJOR_VERSION == 3)
+//#include "opencv/cv.h" // Sometimes cause strange errors in debug and C++ mode due to the redefinition of free()...
+//#include "opencv/cvwimage.h"
+//#include "opencv/cxcore.h"
+//#include "opencv/highgui.h"
+#include "opencv2/core/core_c.h"
+#include "opencv2/imgproc/imgproc_c.h"
+#include "opencv2/highgui/highgui_c.h"
+#if (CV_MAJOR_VERSION == 3)
+#include "opencv2/imgcodecs/imgcodecs_c.h"
+#include "opencv2/videoio/videoio_c.h"
+#endif // (CV_MAJOR_VERSION == 3)
+#if (CV_MAJOR_VERSION >= 4)
+#include "opencv2/imgcodecs/legacy/constants_c.h"
+#include "opencv2/videoio/legacy/constants_c.h"
+#include "opencv2/videoio/videoio_c.h"
+#endif // (CV_MAJOR_VERSION >= 4)
+// The following headers do not build in C mode.
+#ifdef __cplusplus
+#if ((CV_MAJOR_VERSION == 2) || (CV_MAJOR_VERSION == 3))
+//#include "opencv/cvaux.h" // Not found on Ubuntu 12.04...?
+//#include "opencv/cxmisc.h"
+//#include "opencv/ml.h"
+#endif // ((CV_MAJOR_VERSION == 2) || (CV_MAJOR_VERSION == 3))
+#include "opencv2/core/core.hpp"
+#include "opencv2/imgproc/imgproc.hpp"
+#include "opencv2/highgui/highgui.hpp"
+#if (CV_MAJOR_VERSION >= 3)
+#include "opencv2/imgcodecs/imgcodecs.hpp"
+#include "opencv2/videoio/videoio.hpp"
+#endif // (CV_MAJOR_VERSION >= 3)
+//#include "opencv2/contrib/contrib.hpp"
+#endif // __cplusplus
+#endif // (CV_MAJOR_VERSION >= 2)
+
+// min and max may be undefined so we need to redefine them here...
+#if (CV_MAJOR_VERSION >= 2)
+#ifdef _MSC_VER
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif // !max
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif // !min
+#endif // _MSC_VER
+#endif // (CV_MAJOR_VERSION >= 2)
+
+// Some macros might be missing depending on OpenCV versions...
+#ifndef DISABLE_OPENCV_COMPAT_MACROS
+#define DISABLE_OPENCV_COMPAT_MACROS // Needed to avoid redefinition errors...
+#ifdef __cplusplus
+#if (CV_MAJOR_VERSION < 3)
+namespace cv
+{
+ enum
+ {
+ CAP_PROP_FRAME_WIDTH = CV_CAP_PROP_FRAME_WIDTH,
+ CAP_PROP_FRAME_HEIGHT = CV_CAP_PROP_FRAME_HEIGHT
+ };
+
+ // Don't know how to define cv::VideoWriter::fourcc...
+
+}
+#endif // (CV_MAJOR_VERSION < 3)
+#endif // __cplusplus
+#endif // !DISABLE_OPENCV_COMPAT_MACROS
+
+// The ENTER key code seems to vary depending on OpenCV versions...
+#ifndef CV_KEY_CODE_ENTER
+#ifdef _WIN32
+#define CV_KEY_CODE_ENTER 13
+#else
+#if (CV_MAJOR_VERSION >= 4)
+#define CV_KEY_CODE_ENTER 13
+#else
+#ifdef __APPLE__
+#define CV_KEY_CODE_ENTER 13
+#else
+#define CV_KEY_CODE_ENTER 10
+#endif // __APPLE__
+#endif // (CV_MAJOR_VERSION >= 4)
+#endif // _WIN32
+#endif // !CV_KEY_CODE_ENTER
+
+// CV_RGB does not always work with CvScalar after OpenCV 4.2.0...
+#ifndef CV_RGB_CvScalar
+#define CV_RGB_CvScalar(r, g, b) cvScalar((b), (g), (r), 0)
+#endif // !CV_RGB_CvScalar
+
+#if (CV_MAJOR_VERSION >= 4)
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
+#define USE_OPENCV_HIGHGUI_CPP_API
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
+#endif // (CV_MAJOR_VERSION >= 4)
+
+#ifdef __GNUC__
+// Restore the GCC warnings previously disabled.
+#if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
+#pragma GCC diagnostic pop
+#else
+//#pragma GCC diagnostic warning "-Wunknown-pragmas"
+//#pragma GCC diagnostic warning "-Wuninitialized"
+//#pragma GCC diagnostic warning "-Wcomment"
+//#pragma GCC diagnostic warning "-Wunused"
+#pragma GCC diagnostic warning "-Wunused-function"
+//#pragma GCC diagnostic warning "-Wunused-value"
+//#pragma GCC diagnostic warning "-Wunused-variable"
+//#pragma GCC diagnostic warning "-Wunused-parameter"
+//#if (__GNUC__ >= 9)
+//#pragma GCC diagnostic warning "-Wclass-memaccess"
+//#pragma GCC diagnostic warning "-Wdeprecated-copy"
+//#endif // (__GNUC__ >= 9)
+#endif // (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
+#endif // __GNUC__
+
+#ifdef __BORLANDC__
+// Restore the Borland C++ Builder warnings previously disabled.
+#pragma warn .8019
+#endif // __BORLANDC__
+
+#ifdef _MSC_VER
+// Restore the Visual Studio warnings previously disabled.
+#pragma warning(default : 6385)
+#pragma warning(default : 6294)
+#pragma warning(default : 6201)
+#pragma warning(default : 6204)
+#pragma warning(default : 4996)
+#pragma warning(default : 4458)
+#pragma warning(default : 4100)
+#endif // _MSC_VER
+
+#endif // !CVINC_H
diff --git a/CamSvcSrv/jni/Globals.c b/CamSvcSrv/jni/Globals.cpp
similarity index 71%
rename from CamSvcSrv/jni/Globals.c
rename to CamSvcSrv/jni/Globals.cpp
index 9ed2d06..ae06b37 100644
--- a/CamSvcSrv/jni/Globals.c
+++ b/CamSvcSrv/jni/Globals.cpp
@@ -9,25 +9,40 @@
#include "Globals.h"
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
CvCapture* webcam = NULL;
CvVideoWriter* videorecordfile = NULL;
+#else
+cv::VideoCapture* webcam = NULL;
+cv::Mat* pframemat = NULL;
+IplImage frameipl;
+cv::VideoWriter videorecordfile;
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
#ifndef DISABLE_TIMER_RECORDING
TIMER timer;
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
CHRONO chrono;
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
CvFont font;
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
CRITICAL_SECTION imageCS;
IplImage* frame = NULL;
IplImage* resizedframe = NULL;
IplImage* image = NULL;
IplImage* previmage = NULL;
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
IplImage* detectimage = NULL;
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
char* databuf = NULL;
int databuflen = 0;
char* sharedbuf = NULL;
int sharedbuflen = 0;
CRITICAL_SECTION sharedbufCS;
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
int encodeparams[2];
+#else
+std::vector encodeparams;
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
BOOL bStop = FALSE;
// Parameters.
@@ -54,3 +69,4 @@ int encodequality = 0;
char encodetype[32];
int method = 0;
BOOL bDisableVideoRecording = FALSE;
+char szVideoRecordCodec[5];
diff --git a/CamSvcSrv/jni/Globals.h b/CamSvcSrv/jni/Globals.h
index 30b0b93..5bab565 100644
--- a/CamSvcSrv/jni/Globals.h
+++ b/CamSvcSrv/jni/Globals.h
@@ -14,38 +14,55 @@
#include "OSCriticalSection.h"
#ifndef DISABLE_TIMER_RECORDING
#include "OSTimer.h"
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
#include "OSNet.h"
-#include "CvCore.h"
+#include "CvInc.h"
#ifdef ENABLE_CVKINECT2SDKHOOK
-#ifndef INCLUDE_HEADERS_OUTSIDE_CVKINECT2SDKHOOK
-#define INCLUDE_HEADERS_OUTSIDE_CVKINECT2SDKHOOK
-#endif // INCLUDE_HEADERS_OUTSIDE_CVKINECT2SDKHOOK
-#include
#include "CvKinect2SDKHook.h"
#endif // ENABLE_CVKINECT2SDKHOOK
// Use SOMAXCONN as the max number of simultaneous clients for multithreaded version...
+#ifdef __ANDROID__
+#define VID_FOLDER "/storage/sdcard0/download/"
+#else
+#define VID_FOLDER ""
+#endif // __ANDROID__
+
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
EXTERN_C CvCapture* webcam;
EXTERN_C CvVideoWriter* videorecordfile;
+#else
+extern cv::VideoCapture* webcam;
+extern cv::Mat* pframemat;
+extern IplImage frameipl;
+extern cv::VideoWriter videorecordfile;
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
#ifndef DISABLE_TIMER_RECORDING
EXTERN_C TIMER timer;
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
EXTERN_C CHRONO chrono;
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
EXTERN_C CvFont font;
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
EXTERN_C CRITICAL_SECTION imageCS;
EXTERN_C IplImage* frame;
EXTERN_C IplImage* resizedframe;
EXTERN_C IplImage* image;
EXTERN_C IplImage* previmage;
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
EXTERN_C IplImage* detectimage;
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
EXTERN_C char* databuf;
EXTERN_C int databuflen;
EXTERN_C char* sharedbuf;
EXTERN_C int sharedbuflen;
EXTERN_C CRITICAL_SECTION sharedbufCS;
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
EXTERN_C int encodeparams[2];
+#else
+extern std::vector encodeparams;
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
EXTERN_C BOOL bStop;
// Parameters.
@@ -72,5 +89,6 @@ EXTERN_C int encodequality;
EXTERN_C char encodetype[32];
EXTERN_C int method;
EXTERN_C BOOL bDisableVideoRecording;
+EXTERN_C char szVideoRecordCodec[5];
-#endif // GLOBALS_H
+#endif // !GLOBALS_H
diff --git a/CamSvcSrv/jni/Main.c b/CamSvcSrv/jni/Main.cpp
similarity index 63%
rename from CamSvcSrv/jni/Main.c
rename to CamSvcSrv/jni/Main.cpp
index e64d182..f977019 100644
--- a/CamSvcSrv/jni/Main.c
+++ b/CamSvcSrv/jni/Main.cpp
@@ -1,5 +1,15 @@
#include "Globals.h"
+// min and max might cause incompatibilities with GCC...
+#ifndef _MSC_VER
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif // !max
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif // !min
+#endif // !_MSC_VER
+
int LoadConfig()
{
FILE* file = NULL;
@@ -33,6 +43,8 @@ int LoadConfig()
sprintf(encodetype, ".JPEG");
method = 3;
bDisableVideoRecording = 0;
+ memset(szVideoRecordCodec, 0, sizeof(szVideoRecordCodec));
+ sprintf(szVideoRecordCodec, "WMV2");
#ifdef __ANDROID__
file = fopen("/storage/sdcard0/download/RemoteWebcamMultiSrv.txt", "r");
@@ -88,6 +100,8 @@ int LoadConfig()
if (sscanf(line, "%d", &method) != 1) printf("Invalid configuration file.\n");
if (fgets3(file, line, sizeof(line)) == NULL) printf("Invalid configuration file.\n");
if (sscanf(line, "%d", &bDisableVideoRecording) != 1) printf("Invalid configuration file.\n");
+ if (fgets3(file, line, sizeof(line)) == NULL) printf("Invalid configuration file.\n");
+ if (sscanf(line, "%[^\r\n]4s", szVideoRecordCodec) != 1) printf("Invalid configuration file.\n");
if (fclose(file) != EXIT_SUCCESS) printf("fclose() failed.\n");
}
else
@@ -129,22 +143,42 @@ int LoadConfig()
return EXIT_SUCCESS;
}
-int MovementDetection(IplImage* previmg, IplImage* img, IplImage* detectimg, char* buf, int* pnbBytes)
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
+inline int MovementDetection(IplImage* previmg, IplImage* img, IplImage* detectimg, char* buf, int* pnbBytes,
+ char* enctype, int* encparams, int pixcolorchgthresh)
+#else
+inline int MovementDetection(IplImage* previmg, IplImage* img, IplImage* detectimg, char* buf, int* pnbBytes,
+ char* enctype, std::vector& encparams, int pixcolorchgthresh)
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
{
unsigned int i = 0, val = 0, count = 0, indexb = 0, indexg = 0, indexr = 0;
int r = 0, g = 0, b = 0;
unsigned char* prevdata = (unsigned char*)previmg->imageData;
unsigned char* data = (unsigned char*)img->imageData;
- unsigned char* detectdata = (unsigned char*)detectimg->imageData;
+ unsigned char* detectdata = NULL;
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
CvMat* mat = NULL;
+#else
+ std::vector bufmatvector;
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
+
+ if (detectimg) detectdata = (unsigned char*)detectimg->imageData;
// First compute the static compression to be able to compare with the time compression.
- mat = cvEncodeImage(encodetype, img, encodeparams);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
+ mat = cvEncodeImage(enctype, img, encparams);
if (mat == NULL)
{
- printf("cvMat() failed.\n");
+ printf("cvEncodeImage() failed.\n");
return EXIT_FAILURE;
}
+#else
+ if (!cv::imencode(enctype, cv::cvarrToMat(img), bufmatvector, encparams))
+ {
+ printf("cv::imencode() failed.\n");
+ return EXIT_FAILURE;
+ }
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
// Reserved for number of bytes sent and image dimensions.
count = 3*sizeof(unsigned int);
@@ -159,7 +193,7 @@ int MovementDetection(IplImage* previmg, IplImage* img, IplImage* detectimg, cha
b = data[indexb]-prevdata[indexb];
g = data[indexg]-prevdata[indexg];
r = data[indexr]-prevdata[indexr];
- if ((abs(b)+abs(g)+abs(r)) > 3*pixcolorchgthreshold)
+ if ((abs(b)+abs(g)+abs(r)) > 3*pixcolorchgthresh)
{
// Blue index value of the pixel.
memcpy(buf+count, (char*)&i, sizeof(unsigned int));
@@ -167,16 +201,24 @@ int MovementDetection(IplImage* previmg, IplImage* img, IplImage* detectimg, cha
// BGR values.
memcpy(buf+count, img->imageData+i, 3*sizeof(char));
count += 3*sizeof(char);
- // Show in green pixels that significantly changed.
- detectdata[indexb] = 0;
- detectdata[indexg] = 255;
- detectdata[indexr] = 0;
+ if (detectimg)
+ {
+ // Show in green pixels that significantly changed.
+ detectdata[indexb] = 0;
+ detectdata[indexg] = 255;
+ detectdata[indexr] = 0;
+ }
}
// A full image will be sent if the time compression is worse than the static one.
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if (count > (unsigned int)(mat->rows*mat->cols)) break;
- }
+#else
+ if (count > bufmatvector.size()) break;
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
+ }
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if (count > (unsigned int)(mat->rows*mat->cols))
{
val = UINT_MAX; // Special number to indicate a full image.
@@ -188,6 +230,25 @@ int MovementDetection(IplImage* previmg, IplImage* img, IplImage* detectimg, cha
memcpy(buf+3*sizeof(unsigned int), mat->data.ptr, (size_t)(mat->rows*mat->cols));
count = 3*sizeof(unsigned int)+(unsigned int)(mat->rows*mat->cols);
}
+#else
+ if (count > bufmatvector.size())
+ {
+ val = UINT_MAX; // Special number to indicate a full image.
+ memcpy(buf, (char*)&val, sizeof(unsigned int));
+ // Static compressed image dimensions.
+ i = bufmatvector.size();
+ memcpy(buf+sizeof(unsigned int), (char*)&i, sizeof(unsigned int));
+ i = 1;
+ memcpy(buf+2*sizeof(unsigned int), (char*)&i, sizeof(unsigned int));
+ // Full image data (with static compression).
+ i = bufmatvector.size();
+ while (i--)
+ {
+ buf[3*sizeof(unsigned int)+i] = (char)bufmatvector[i];
+ }
+ count = 3*sizeof(unsigned int)+bufmatvector.size();
+ }
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
else
{
val = count; // Number of bytes sent.
@@ -199,19 +260,35 @@ int MovementDetection(IplImage* previmg, IplImage* img, IplImage* detectimg, cha
*pnbBytes = (int)count;
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
cvReleaseMat(&mat);
+#else
+ bufmatvector.clear();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
return EXIT_SUCCESS;
}
-int MovementDetection2(IplImage* previmg, IplImage* img, IplImage* detectimg, char* buf, int* pnbBytes)
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
+inline int MovementDetection2(IplImage* previmg, IplImage* img, IplImage* detectimg, char* buf, int* pnbBytes,
+ char* enctype, int* encparams, int pixcolorchgthresh, int timecompressiondividerthresh)
+#else
+inline int MovementDetection2(IplImage* previmg, IplImage* img, IplImage* detectimg, char* buf, int* pnbBytes,
+ char* enctype, std::vector& encparams, int pixcolorchgthresh, int timecompressiondividerthresh)
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
{
unsigned int i = 0, val = 0, count = 0, indexb = 0, indexg = 0, indexr = 0;
int r = 0, g = 0, b = 0;
unsigned char* prevdata = (unsigned char*)previmg->imageData;
unsigned char* data = (unsigned char*)img->imageData;
- unsigned char* detectdata = (unsigned char*)detectimg->imageData;
+ unsigned char* detectdata = NULL;
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
CvMat* mat = NULL;
+#else
+ std::vector bufmatvector;
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
+
+ if (detectimg) detectdata = (unsigned char*)detectimg->imageData;
// Reserved for number of bytes sent and image dimensions.
count = 3*sizeof(unsigned int);
@@ -226,7 +303,7 @@ int MovementDetection2(IplImage* previmg, IplImage* img, IplImage* detectimg, ch
b = data[indexb]-prevdata[indexb];
g = data[indexg]-prevdata[indexg];
r = data[indexr]-prevdata[indexr];
- if ((abs(b)+abs(g)+abs(r)) > 3*pixcolorchgthreshold)
+ if ((abs(b)+abs(g)+abs(r)) > 3*pixcolorchgthresh)
{
// Blue index value of the pixel.
memcpy(buf+count, (char*)&i, sizeof(unsigned int));
@@ -234,21 +311,25 @@ int MovementDetection2(IplImage* previmg, IplImage* img, IplImage* detectimg, ch
// BGR values.
memcpy(buf+count, img->imageData+i, 3*sizeof(char));
count += 3*sizeof(char);
- // Show in green pixels that significantly changed.
- detectdata[indexb] = 0;
- detectdata[indexg] = 255;
- detectdata[indexr] = 0;
+ if (detectimg)
+ {
+ // Show in green pixels that significantly changed.
+ detectdata[indexb] = 0;
+ detectdata[indexg] = 255;
+ detectdata[indexr] = 0;
+ }
}
// A full image will be sent if the time compression is bad.
- if (count > (unsigned int)(img->imageSize/timecompressiondividerthreshold)) break;
+ if (count > (unsigned int)(img->imageSize/timecompressiondividerthresh)) break;
}
- if (count > (unsigned int)(img->imageSize/timecompressiondividerthreshold))
+ if (count > (unsigned int)(img->imageSize/timecompressiondividerthresh))
{
val = UINT_MAX; // Special number to indicate a full image.
memcpy(buf, (char*)&val, sizeof(unsigned int));
- mat = cvEncodeImage(encodetype, img, encodeparams);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
+ mat = cvEncodeImage(enctype, img, encparams);
if (mat == NULL)
{
printf("cvMat() failed.\n");
@@ -261,6 +342,26 @@ int MovementDetection2(IplImage* previmg, IplImage* img, IplImage* detectimg, ch
memcpy(buf+3*sizeof(unsigned int), mat->data.ptr, (size_t)(mat->rows*mat->cols));
count = 3*sizeof(unsigned int)+(unsigned int)(mat->rows*mat->cols);
cvReleaseMat(&mat);
+#else
+ if (!cv::imencode(enctype, cv::cvarrToMat(img), bufmatvector, encparams))
+ {
+ printf("cv::imencode() failed.\n");
+ return EXIT_FAILURE;
+ }
+ // Static compressed image dimensions.
+ i = bufmatvector.size();
+ memcpy(buf+sizeof(unsigned int), (char*)&i, sizeof(unsigned int));
+ i = 1;
+ memcpy(buf+2*sizeof(unsigned int), (char*)&i, sizeof(unsigned int));
+ // Full image data (with static compression).
+ i = bufmatvector.size();
+ while (i--)
+ {
+ buf[3*sizeof(unsigned int)+i] = (char)bufmatvector[i];
+ }
+ count = 3*sizeof(unsigned int)+bufmatvector.size();
+ bufmatvector.clear();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
}
else
{
@@ -345,6 +446,10 @@ int handlecli(SOCKET sockcli, void* pParam)
free(sendbuf);
return EXIT_FAILURE;
}
+
+ // See https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html,
+ // https://stackoverflow.com/questions/47729941/mjpeg-over-http-specification...
+
memset(httpbuf, 0, sizeof(httpbuf));
sprintf(httpbuf,
"HTTP/1.1 200 OK\r\n"
@@ -354,9 +459,10 @@ int handlecli(SOCKET sockcli, void* pParam)
//"Expires: 0\r\n"
//"Cache-Control: no-cache, private, no-store, must-revalidate, pre-check = 0, post-check = 0, max-age = 0\r\n"
//"Pragma: no-cache\r\n"
- "Content-Type: multipart/x-mixed-replace; boundary=--boundary\r\n"
+ "Content-Type: multipart/x-mixed-replace; boundary=boundary\r\n"
//"Media-type: image/jpeg\r\n"
- "\r\n");
+ //"\r\n" // CRLF will be in the next encapsulation boundary "\r\n--boundary\r\n"...
+ );
if (sendall(sockcli, httpbuf, strlen(httpbuf)) != EXIT_SUCCESS)
{
free(sendbuf);
@@ -384,7 +490,7 @@ int handlecli(SOCKET sockcli, void* pParam)
free(sendbuf);
return EXIT_FAILURE;
}
- mSleep(captureperiod);
+ uSleep(1000*captureperiod);
break;
}
@@ -401,16 +507,24 @@ void CleanUp(void)
// Ensure the video recording is correctly stopped.
#ifndef DISABLE_TIMER_RECORDING
DeleteTimer(&timer, FALSE);
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if (videorecordfile) cvReleaseVideoWriter(&videorecordfile);
videorecordfile = NULL;
+#else
+ if (videorecordfile.isOpened()) videorecordfile.release();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
bStop = TRUE;
StopChronoQuick(&chrono);
#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
cvDestroyWindow("Detection");
-#endif // DISABLE_GUI_REMOTEWEBCAMMULTISRV
+#else
+ cv::destroyWindow("Detection");
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
cvReleaseImage(&detectimage);
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
cvReleaseImage(&previmage);
free(databuf);
mSleep(15000);
@@ -423,14 +537,19 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
CvMat M = cvMat(2, 3, CV_64F, m); // For rotation...
double hcenter0 = 0, vcenter0 = 0, hshift0 = 0, vshift0 = 0;
int nbBytes = 0;
- char szText[256];
unsigned int val = 0;
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
CvMat* mat = NULL;
+#else
+ std::vector bufmatvector;
+ unsigned int i = 0;
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
BOOL bForceSendFullImg = TRUE;
char httpbuf[2048];
#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
+ char szText[256];
int c = 0;
-#endif // DISABLE_GUI_REMOTEWEBCAMMULTISRV
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
UNREFERENCED_PARAMETER(pParam);
@@ -447,6 +566,7 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
free(databuf);
return 0;
}
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
detectimage = cvCloneImage(image);
if (!detectimage)
{
@@ -455,20 +575,29 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
free(databuf);
return 0;
}
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
cvNamedWindow("Detection", CV_WINDOW_AUTOSIZE);
cvMoveWindow("Detection", 0, 0);
cvShowImage("Detection", image);
cvWaitKey(10);
+#else
+ cv::namedWindow("Detection", cv::WINDOW_AUTOSIZE);
+ cv::moveWindow("Detection", 0, 0);
+ cv::imshow("Detection", cv::cvarrToMat(image));
+ cv::waitKey(10);
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
#else
mSleep(10);
-#endif // DISABLE_GUI_REMOTEWEBCAMMULTISRV
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
StartChrono(&chrono);
for (;;)
{
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
frame = cvQueryFrame(webcam);
if (!frame)
{
@@ -476,6 +605,17 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
CleanUp();
return 0;
}
+#else
+ if (!webcam->read(*pframemat))
+ {
+ printf("Error getting an image from the webcam.\n");
+ CleanUp();
+ return 0;
+ }
+ frameipl = (IplImage)*pframemat;
+ frame = &frameipl;
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
+
if (bForceSoftwareResize) cvResize(frame, resizedframe, CV_INTER_LINEAR);
else resizedframe = frame;
@@ -508,16 +648,28 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
LeaveCriticalSection(&imageCS);
#ifdef DISABLE_TIMER_RECORDING
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if ((videorecordfile != NULL)&&(image != NULL))
{
- if (!cvWriteFrame(videorecordfile, image))
+ if (!cvWriteFrame(videorecordfile, image))
+#else
+ if ((videorecordfile.isOpened())&&(image != NULL))
+ {
+ try
+ {
+ videorecordfile.write(cv::cvarrToMat(image));
+ }
+ catch (...)
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
{
printf("Error writing to a video file.\n");
}
}
#endif // DISABLE_TIMER_RECORDING
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
cvCopy(image, detectimage, NULL);
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
if (
((method == 0)||(method == 1))&&
@@ -528,10 +680,11 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
bForceSendFullImg = FALSE;
val = UINT_MAX; // Special number to indicate a full image with static compression.
memcpy(databuf, (char*)&val, sizeof(unsigned int));
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
mat = cvEncodeImage(encodetype, image, encodeparams);
if (mat == NULL)
{
- printf("cvMat() failed.\n");
+ printf("cvEncodeImage() failed.\n");
CleanUp();
return 0;
}
@@ -542,8 +695,31 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
memcpy(databuf+3*sizeof(unsigned int), mat->data.ptr, (size_t)(mat->rows*mat->cols));
nbBytes = 3*sizeof(unsigned int)+(unsigned int)(mat->rows*mat->cols);
cvReleaseMat(&mat);
+#else
+ if (!cv::imencode(encodetype, cv::cvarrToMat(image), bufmatvector, encodeparams))
+ {
+ printf("cv::imencode() failed.\n");
+ CleanUp();
+ return 0;
+ }
+ // Static compressed image dimensions.
+ i = bufmatvector.size();
+ memcpy(databuf+sizeof(unsigned int), (char*)&i, sizeof(unsigned int));
+ i = 1;
+ memcpy(databuf+2*sizeof(unsigned int), (char*)&i, sizeof(unsigned int));
+ // Full image data (with static compression).
+ i = bufmatvector.size();
+ while (i--)
+ {
+ databuf[3*sizeof(unsigned int)+i] = (char)bufmatvector[i];
+ }
+ nbBytes = 3*sizeof(unsigned int)+bufmatvector.size();
+ bufmatvector.clear();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
sprintf(szText, "Periodic complete image : %d bytes", nbBytes);
cvPutText(detectimage, szText, cvPoint(0,48), &font, CV_RGB(255,0,0));
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
StartChrono(&chrono);
}
else
@@ -551,14 +727,26 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
switch (method)
{
case 0:
- if (MovementDetection(previmage, image, detectimage, databuf, &nbBytes) != EXIT_SUCCESS)
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
+ if (MovementDetection(previmage, image, detectimage, databuf, &nbBytes,
+ encodetype, encodeparams, pixcolorchgthreshold) != EXIT_SUCCESS)
+#else
+ if (MovementDetection(previmage, image, NULL, databuf, &nbBytes,
+ encodetype, encodeparams, pixcolorchgthreshold) != EXIT_SUCCESS)
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
{
CleanUp();
return 0;
}
break;
case 1:
- if (MovementDetection2(previmage, image, detectimage, databuf, &nbBytes) != EXIT_SUCCESS)
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
+ if (MovementDetection2(previmage, image, detectimage, databuf, &nbBytes,
+ encodetype, encodeparams, pixcolorchgthreshold, timecompressiondividerthreshold) != EXIT_SUCCESS)
+#else
+ if (MovementDetection2(previmage, image, NULL, databuf, &nbBytes,
+ encodetype, encodeparams, pixcolorchgthreshold, timecompressiondividerthreshold) != EXIT_SUCCESS)
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
{
CleanUp();
return 0;
@@ -576,16 +764,17 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
break;
case 3:
nbBytes = 0;
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
mat = cvEncodeImage(encodetype, image, encodeparams);
if (mat == NULL)
{
- printf("cvMat() failed.\n");
+ printf("cvEncodeImage() failed.\n");
CleanUp();
return 0;
}
memset(httpbuf, 0, sizeof(httpbuf));
- sprintf(httpbuf,
- "--boundary\r\n"
+ sprintf(httpbuf,
+ "\r\n--boundary\r\n"
"Content-Type: image/jpeg\r\n"
"Content-Length: %d\r\n"
"\r\n", mat->rows*mat->cols);
@@ -595,6 +784,30 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
memcpy(databuf+nbBytes, mat->data.ptr, (size_t)(mat->rows*mat->cols));
nbBytes += (mat->rows*mat->cols);
cvReleaseMat(&mat);
+#else
+ if (!cv::imencode(encodetype, cv::cvarrToMat(image), bufmatvector, encodeparams))
+ {
+ printf("cv::imencode() failed.\n");
+ CleanUp();
+ return 0;
+ }
+ memset(httpbuf, 0, sizeof(httpbuf));
+ sprintf(httpbuf,
+ "\r\n--boundary\r\n"
+ "Content-Type: image/jpeg\r\n"
+ "Content-Length: %d\r\n"
+ "\r\n", (int)bufmatvector.size());
+ memcpy(databuf+nbBytes, httpbuf, strlen(httpbuf));
+ nbBytes += strlen(httpbuf);
+ // Full image data (with static compression).
+ i = bufmatvector.size();
+ while (i--)
+ {
+ databuf[nbBytes+i] = (char)bufmatvector[i];
+ }
+ nbBytes += (int)bufmatvector.size();
+ bufmatvector.clear();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
break;
default:
printf("Invalid parameter.\n");
@@ -602,8 +815,10 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
return 0;
break;
}
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
sprintf(szText, "Data transmitted : %d bytes", nbBytes);
cvPutText(detectimage, szText, cvPoint(0,32), &font, CV_RGB(255,0,0));
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
}
EnterCriticalSection(&sharedbufCS);
@@ -611,34 +826,48 @@ THREAD_PROC_RETURN_VALUE handlecam(void* pParam)
memcpy(sharedbuf, databuf, nbBytes);
LeaveCriticalSection(&sharedbufCS);
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
sprintf(szText, "Uncompressed size : %d bytes", image->imageSize);
cvPutText(detectimage, szText, cvPoint(0,16), &font, CV_RGB(255,0,0));
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
cvCopy(image, previmage, NULL);
#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
cvShowImage("Detection", detectimage);
-
c = cvWaitKey(captureperiod);
+#else
+ cv::imshow("Detection", cv::cvarrToMat(detectimage));
+ c = cv::waitKey(captureperiod);
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
if ((char)c == 27) break;
#else
- mSleep(captureperiod);
-#endif // DISABLE_GUI_REMOTEWEBCAMMULTISRV
+ uSleep(1000*captureperiod);
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
if (bStop) break;
}
// Ensure the video recording is correctly stopped.
#ifndef DISABLE_TIMER_RECORDING
DeleteTimer(&timer, FALSE);
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if (videorecordfile) cvReleaseVideoWriter(&videorecordfile);
videorecordfile = NULL;
+#else
+ if (videorecordfile.isOpened()) videorecordfile.release();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
bStop = TRUE;
StopChronoQuick(&chrono);
#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
cvDestroyWindow("Detection");
-#endif // DISABLE_GUI_REMOTEWEBCAMMULTISRV
+#else
+ cv::destroyWindow("Detection");
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
cvReleaseImage(&detectimage);
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
cvReleaseImage(&previmage);
mSleep(15000);
exit(EXIT_SUCCESS);
@@ -653,16 +882,26 @@ TIMERCALLBACK_RETURN_VALUE VideoRecordCallbackFunction(void* pParam, BOOLEAN b)
UNREFERENCED_PARAMETER(b);
EnterCriticalSection(&imageCS);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if ((videorecordfile != NULL)&&(image != NULL))
{
- if (!cvWriteFrame(videorecordfile, image))
+ if (!cvWriteFrame(videorecordfile, image))
+#else
+ if ((videorecordfile.isOpened())&&(image != NULL))
+ {
+ try
+ {
+ videorecordfile.write(cv::cvarrToMat(image));
+ }
+ catch (...)
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
{
printf("Error writing to a video file.\n");
}
}
LeaveCriticalSection(&imageCS);
}
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
int quitall()
{
@@ -694,7 +933,9 @@ int main(int argc, char* argv[])
CvMat M = cvMat(2, 3, CV_64F, m); // For rotation...
double hcenter0 = 0, vcenter0 = 0, hshift0 = 0, vshift0 = 0;
THREAD_IDENTIFIER handlecamThreadId;
+ char videorecordextension[16];
char videorecordfilename[256];
+ double fps = 0;
int i = 0;
#ifndef __ANDROID__
@@ -702,28 +943,46 @@ int main(int argc, char* argv[])
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
-#endif // __ANDROID__
+#endif // !__ANDROID__
LoadConfig();
if (strncmp(encodetype, ".JPEG", min(strlen(encodetype), strlen(".JPEG"))+1) == 0)
{
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
encodeparams[0] = CV_IMWRITE_JPEG_QUALITY;
encodeparams[1] = encodequality;
+#else
+ encodeparams.push_back(cv::IMWRITE_JPEG_QUALITY);
+ encodeparams.push_back(encodequality);
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
}
else if (strncmp(encodetype, ".PNG", min(strlen(encodetype), strlen(".PNG"))+1) == 0)
{
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
encodeparams[0] = CV_IMWRITE_PNG_COMPRESSION;
encodeparams[1] = encodequality;
+#else
+ encodeparams.push_back(cv::IMWRITE_PNG_COMPRESSION);
+ encodeparams.push_back(encodequality);
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
}
else
{
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
encodeparams[0] = CV_IMWRITE_PXM_BINARY;
encodeparams[1] = encodequality;
+#else
+ encodeparams.push_back(cv::IMWRITE_PXM_BINARY);
+ encodeparams.push_back(encodequality);
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
}
+#ifndef DISABLE_GUI_REMOTEWEBCAMMULTISRV
cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, 8);
+#endif // !DISABLE_GUI_REMOTEWEBCAMMULTISRV
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if ((strlen(szDevPath) == 1)&&(isdigit(szDevPath[0])))
{
webcam = cvCreateCameraCapture(atoi(szDevPath));
@@ -732,7 +991,7 @@ int main(int argc, char* argv[])
{
webcam = cvCreateFileCapture(szDevPath);
}
- if (!webcam)
+ if (!webcam)
{
printf("Error opening the webcam.\n");
return EXIT_FAILURE;
@@ -758,6 +1017,75 @@ int main(int argc, char* argv[])
cvReleaseCapture(&webcam);
return EXIT_FAILURE;
}
+#else
+ pframemat = new cv::Mat();
+ if (!pframemat)
+ {
+ printf("Out of memory.\n");
+ encodeparams.clear();
+ return EXIT_FAILURE;
+ }
+ webcam = new cv::VideoCapture();
+ if (!webcam)
+ {
+ printf("Out of memory.\n");
+ delete pframemat;
+ encodeparams.clear();
+ return EXIT_FAILURE;
+ }
+ if ((strlen(szDevPath) == 1)&&(isdigit(szDevPath[0])))
+ {
+ if (!webcam->open(atoi(szDevPath)))
+ {
+ printf("Error opening the webcam.\n");
+ delete webcam;
+ delete pframemat;
+ encodeparams.clear();
+ return EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ if (!webcam->open(szDevPath))
+ {
+ printf("Error opening the webcam.\n");
+ delete webcam;
+ delete pframemat;
+ encodeparams.clear();
+ return EXIT_FAILURE;
+ }
+ }
+
+#if (CV_MAJOR_VERSION < 3)
+ webcam->set(CV_CAP_PROP_FRAME_WIDTH, videoimgwidth);
+ webcam->set(CV_CAP_PROP_FRAME_HEIGHT, videoimgheight);
+#else
+ webcam->set(cv::CAP_PROP_FRAME_WIDTH, videoimgwidth);
+ webcam->set(cv::CAP_PROP_FRAME_HEIGHT, videoimgheight);
+#endif // (CV_MAJOR_VERSION < 3)
+
+ // Sometimes the first images are bad, so wait a little bit and take
+ // several images in the beginning.
+ i = 0;
+ while (i < 2)
+ {
+ mSleep(500);
+ webcam->read(*pframemat);
+ i++;
+ }
+
+ if (!webcam->read(*pframemat))
+ {
+ printf("Error getting an image from the webcam.\n");
+ webcam->release();
+ delete webcam;
+ delete pframemat;
+ encodeparams.clear();
+ return EXIT_FAILURE;
+ }
+ frameipl = (IplImage)*pframemat;
+ frame = &frameipl;
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
if (bForceSoftwareResize)
{
@@ -765,7 +1093,14 @@ int main(int argc, char* argv[])
if (!resizedframe)
{
printf("Error creating an image.\n");
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
cvReleaseCapture(&webcam);
+#else
+ webcam->release();
+ delete webcam;
+ delete pframemat;
+ encodeparams.clear();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
return EXIT_FAILURE;
}
cvResize(frame, resizedframe, CV_INTER_LINEAR);
@@ -777,7 +1112,14 @@ int main(int argc, char* argv[])
{
printf("Error copying an image.\n");
if (bForceSoftwareResize) cvReleaseImage(&resizedframe);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
cvReleaseCapture(&webcam);
+#else
+ webcam->release();
+ delete webcam;
+ delete pframemat;
+ encodeparams.clear();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
return EXIT_FAILURE;
}
@@ -809,33 +1151,37 @@ int main(int argc, char* argv[])
if (!bDisableVideoRecording)
{
-#ifdef __ANDROID__
- sprintf(videorecordfilename, "/storage/sdcard0/download/video_%.64s.avi", strtime_fns());
- videorecordfile = cvCreateVideoWriter(videorecordfilename,
- CV_FOURCC('M','J','P','G'), // Might work starting with OpenCV 3 for Android?
- //CV_FOURCC('D','I','V','X'),
- //CV_FOURCC('I', 'Y', 'U', 'V'),
-#else
-#ifdef USE_ALTERNATE_RECORDING
- sprintf(videorecordfilename, "video_%.64s.avi", strtime_fns());
- videorecordfile = cvCreateVideoWriter(videorecordfilename,
- CV_FOURCC('M','J','P','G'),
- //CV_FOURCC('D','I','V','X'),
- //CV_FOURCC('I', 'Y', 'U', 'V'),
-#else
- sprintf(videorecordfilename, "video_%.64s.wmv", strtime_fns());
- videorecordfile = cvCreateVideoWriter(videorecordfilename,
- CV_FOURCC('W','M','V','2'),
-#endif // USE_ALTERNATE_RECORDING
-#endif // __ANDROID__
#ifdef DISABLE_TIMER_RECORDING
- 1000.0/(double)(captureperiod+20), // 20 ms is an approximation of the extra time spent for computations...
+ fps = 1000.0/(double)(captureperiod+20); // 20 ms is an approximation of the extra time spent for computations...
#else
- 1000.0/(double)captureperiod,
+ fps = 1000.0/(double)captureperiod;
#endif // DISABLE_TIMER_RECORDING
- cvSize(image->width,image->height),
+ memset(videorecordextension, 0, sizeof(videorecordextension));
+ if (strncmp(szVideoRecordCodec, "WMV2", strlen("WMV2")) == 0) strcpy(videorecordextension, "wmv");
+ else if (strncmp(szVideoRecordCodec, "DIVX", strlen("DIVX")) == 0) strcpy(videorecordextension, "avi");
+ else if (strncmp(szVideoRecordCodec, "XVID", strlen("XVID")) == 0) strcpy(videorecordextension, "avi");
+ else if (strncmp(szVideoRecordCodec, "MJPG", strlen("MJPG")) == 0) strcpy(videorecordextension, "avi");
+ else strcpy(videorecordextension, "avi");
+ sprintf(videorecordfilename, VID_FOLDER"vid_%.64s.%.15s", strtimeex_fns(), videorecordextension);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
+ videorecordfile = cvCreateVideoWriter(videorecordfilename,
+ //CV_FOURCC_PROMPT,
+ CV_FOURCC(szVideoRecordCodec[0], szVideoRecordCodec[1], szVideoRecordCodec[2], szVideoRecordCodec[3]),
+ fps,
+ cvSize(image->width, image->height),
1);
if (!videorecordfile)
+#else
+ if (!videorecordfile.open(videorecordfilename,
+#if (CV_MAJOR_VERSION < 3)
+ CV_FOURCC(szVideoRecordCodec[0], szVideoRecordCodec[1], szVideoRecordCodec[2], szVideoRecordCodec[3]),
+#else
+ cv::VideoWriter::fourcc(szVideoRecordCodec[0], szVideoRecordCodec[1], szVideoRecordCodec[2], szVideoRecordCodec[3]),
+#endif // (CV_MAJOR_VERSION < 3)
+ fps,
+ cvSize(image->width, image->height),
+ 1))
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
{
printf("Error creating a video file.\n");
}
@@ -848,7 +1194,7 @@ int main(int argc, char* argv[])
{
printf("Error creating a timer.\n");
}
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
databuflen = image->imageSize+3*sizeof(unsigned int);
sharedbuflen = 0;
@@ -858,12 +1204,23 @@ int main(int argc, char* argv[])
printf("calloc() failed.\n");
#ifndef DISABLE_TIMER_RECORDING
DeleteTimer(&timer, FALSE);
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
DeleteCriticalSection(&imageCS);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if (videorecordfile) cvReleaseVideoWriter(&videorecordfile);
+#else
+ if (videorecordfile.isOpened()) videorecordfile.release();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
if (bForceSoftwareResize) cvReleaseImage(&resizedframe);
cvReleaseImage(&image);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
cvReleaseCapture(&webcam);
+#else
+ webcam->release();
+ delete webcam;
+ delete pframemat;
+ encodeparams.clear();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
return EXIT_FAILURE;
}
@@ -877,12 +1234,23 @@ int main(int argc, char* argv[])
free(sharedbuf);
#ifndef DISABLE_TIMER_RECORDING
DeleteTimer(&timer, FALSE);
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
DeleteCriticalSection(&imageCS);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if (videorecordfile) cvReleaseVideoWriter(&videorecordfile);
+#else
+ if (videorecordfile.isOpened()) videorecordfile.release();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
if (bForceSoftwareResize) cvReleaseImage(&resizedframe);
cvReleaseImage(&image);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
cvReleaseCapture(&webcam);
+#else
+ webcam->release();
+ delete webcam;
+ delete pframemat;
+ encodeparams.clear();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
return EXIT_FAILURE;
}
@@ -897,12 +1265,23 @@ int main(int argc, char* argv[])
free(sharedbuf);
#ifndef DISABLE_TIMER_RECORDING
DeleteTimer(&timer, FALSE);
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
DeleteCriticalSection(&imageCS);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if (videorecordfile) cvReleaseVideoWriter(&videorecordfile);
+#else
+ if (videorecordfile.isOpened()) videorecordfile.release();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
if (bForceSoftwareResize) cvReleaseImage(&resizedframe);
cvReleaseImage(&image);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
cvReleaseCapture(&webcam);
+#else
+ webcam->release();
+ delete webcam;
+ delete pframemat;
+ encodeparams.clear();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
return EXIT_FAILURE;
}
@@ -925,12 +1304,23 @@ int main(int argc, char* argv[])
free(sharedbuf);
#ifndef DISABLE_TIMER_RECORDING
DeleteTimer(&timer, FALSE);
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
DeleteCriticalSection(&imageCS);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if (videorecordfile) cvReleaseVideoWriter(&videorecordfile);
+#else
+ if (videorecordfile.isOpened()) videorecordfile.release();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
if (bForceSoftwareResize) cvReleaseImage(&resizedframe);
cvReleaseImage(&image);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
cvReleaseCapture(&webcam);
+#else
+ webcam->release();
+ delete webcam;
+ delete pframemat;
+ encodeparams.clear();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
return EXIT_FAILURE;
}
@@ -941,12 +1331,23 @@ int main(int argc, char* argv[])
free(sharedbuf);
#ifndef DISABLE_TIMER_RECORDING
DeleteTimer(&timer, FALSE);
-#endif // DISABLE_TIMER_RECORDING
+#endif // !DISABLE_TIMER_RECORDING
DeleteCriticalSection(&imageCS);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
if (videorecordfile) cvReleaseVideoWriter(&videorecordfile);
+#else
+ if (videorecordfile.isOpened()) videorecordfile.release();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
if (bForceSoftwareResize) cvReleaseImage(&resizedframe);
cvReleaseImage(&image);
- cvReleaseCapture(&webcam);
+#ifndef USE_OPENCV_HIGHGUI_CPP_API
+ cvReleaseCapture(&webcam);
+#else
+ webcam->release();
+ delete webcam;
+ delete pframemat;
+ encodeparams.clear();
+#endif // !USE_OPENCV_HIGHGUI_CPP_API
return EXIT_SUCCESS;
}
diff --git a/CamSvcSrv/jni/OSCore.c b/CamSvcSrv/jni/OSCore.c
index cca8a0a..a220d3e 100644
--- a/CamSvcSrv/jni/OSCore.c
+++ b/CamSvcSrv/jni/OSCore.c
@@ -120,7 +120,7 @@ char* FormatLastErrorMsg(char* buf, int buflen)
// Note that pthreads do not use errno!
-#ifdef __ANDROID__
+#if defined(__ANDROID__) || defined(__APPLE__)
if (strerror_r(errno, lpMsgBuf, (size_t)buflen-3) == EXIT_SUCCESS)
{
// Here the use of snprintf() is mandatory to be sure that buf do not overflow...
@@ -134,7 +134,7 @@ char* FormatLastErrorMsg(char* buf, int buflen)
// GNU version of strerror_r() is strange...
// Here the use of snprintf() is mandatory to be sure that buf do not overflow...
snprintf(buf, (size_t)buflen, "%s. ", strerror_r(errno, lpMsgBuf, (size_t)buflen-3));
-#endif // __ANDROID__
+#endif // defined(__ANDROID__) || defined(__APPLE__)
buf[buflen-1] = 0;
diff --git a/CamSvcSrv/jni/OSCore.h b/CamSvcSrv/jni/OSCore.h
index 07bc05c..221d325 100644
--- a/CamSvcSrv/jni/OSCore.h
+++ b/CamSvcSrv/jni/OSCore.h
@@ -33,6 +33,8 @@ _ Borland C++ Builder : __BORLANDC__
_ GCC : __GNUC__
+_ clang : __clang__
+
Predefined macros depending on the target operating system :
_ 32 bit Windows : _WIN32 & !_WIN64
@@ -49,6 +51,8 @@ _ 64 bit Linux : __linux__ & _LP64
_ Android : __ANDROID__
+_ Mac OS : __APPLE__
+
_ Windows CE : WINCE
*/
@@ -72,10 +76,10 @@ _ Windows CE : WINCE
#if defined(UNICODE) || defined(_UNICODE)
#ifndef UNICODE
#define UNICODE
-#endif // UNICODE
+#endif // !UNICODE
#ifndef _UNICODE
#define _UNICODE
-#endif // _UNICODE
+#endif // !_UNICODE
#endif // defined(UNICODE) || defined(_UNICODE)
#endif // __GNUC__
#endif // _WIN32
@@ -95,7 +99,7 @@ _ Windows CE : WINCE
//# define _CRT_NONSTDC_NO_WARNINGS
//# endif // _CRT_NONSTDC_NO_WARNINGS
-// To avoid compiler warnings about functions compiled as native code (if CLR).
+// To avoid compiler warnings about functions compiled as native code (if /clr).
# if defined(__cplusplus) && defined(_M_CEE)
# pragma warning(disable : 4793)
# endif // defined(__cplusplus) && defined(_M_CEE)
@@ -177,11 +181,17 @@ _ Windows CE : WINCE
#ifndef WINCE
#include // Error Codes Reported by (Some) Library Functions.
#include // Signals.
-#endif // WINCE
+#endif // !WINCE
-#ifdef __GNUC__
-// C99 headers. Some headers are not supported by all the compilers or depends
+// C99 headers. Some headers are not supported by all the compilers or depend
// on its options.
+#ifdef __GNUC__
+
+// See https://stackoverflow.com/questions/3233054/error-int32-max-was-not-declared-in-this-scope
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif // !__STDC_LIMIT_MACROS
+
//#include // Complex arithmetic.
//#include // IEEE-style floating-point arithmetic.
//#include // Integer types.
@@ -192,10 +202,13 @@ _ Windows CE : WINCE
//#include // Wide streams and several kinds of strings.
//#include // Wide characters.
#endif // __GNUC__
+#if defined(_MSC_VER) && _MSC_VER >= 1600
+#include
+#endif // defined(_MSC_VER) && _MSC_VER >= 1600
#ifndef WINCE
#include
-#endif // WINCE
+#endif // !WINCE
#ifdef _WIN32
#include
@@ -203,7 +216,7 @@ _ Windows CE : WINCE
// This must be done if we plan to include Winsock2.h in other files.
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
-#endif // WIN32_LEAN_AND_MEAN
+#endif // !WIN32_LEAN_AND_MEAN
#include
#else
#include
@@ -223,7 +236,7 @@ _ Windows CE : WINCE
#else
#define EXTERN_C extern
#endif // __cplusplus
-#endif // EXTERN_C
+#endif // !EXTERN_C
#ifndef __cplusplus
#ifndef inline
@@ -235,19 +248,20 @@ _ Windows CE : WINCE
#endif // __BORLANDC__
#ifdef __GNUC__
// extern __inline__ in ws2tcpip.h for GNU?
+#ifdef _WIN32
+#if (__MINGW_GNUC_PREREQ(4, 3) && __STDC_VERSION__ >= 199901L) || (defined (__clang__))
+// Problem with the use of inline in _mingw.h for WS2TCPIP_INLINE...
+#include
#define inline static __inline__
+#else
+#define inline static __inline__
+#endif // (__MINGW_GNUC_PREREQ(4, 3) && __STDC_VERSION__ >= 199901L) || (defined (__clang__))
+#else
+#define inline static __inline__
+#endif // _WIN32
#endif // __GNUC__
-#endif // inline
-#endif // __cplusplus
-
-#if !defined(NOMINMAX) || defined(FORCE_MINMAX_DEFINITION)
-#ifndef max
-#define max(a,b) (((a) > (b)) ? (a) : (b))
-#endif // max
-#ifndef min
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#endif // min
-#endif // !defined(NOMINMAX) || defined(FORCE_MINMAX_DEFINITION)
+#endif // !inline
+#endif // !__cplusplus
#ifndef _WIN32
typedef char CHAR;
@@ -259,7 +273,7 @@ typedef unsigned int UINT;
typedef long LONG;
typedef unsigned long ULONG;
typedef float FLOAT;
-#endif // _WIN32
+#endif // !_WIN32
typedef double DOUBLE;
#ifdef __GNUC__
@@ -292,31 +306,42 @@ typedef double DOUBLE;
#endif
#endif // WINCE
+// The definition of M_PI and M_PI_2 is not in C++ standard, although it is often provided by compilers...
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif // !M_PI
+#ifndef M_PI_2
+#define M_PI_2 1.57079632679489661923
+#endif // !M_PI_2
+
#ifndef _WIN32
//#ifndef ZeroMemory
#define ZeroMemory(Destination,Length) memset((Destination),0,(Length))
-//#endif // ZeroMemory
+//#endif // !ZeroMemory
typedef void* HANDLE;
//#ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
-//#endif // INVALID_HANDLE_VALUE
+//#endif // !INVALID_HANDLE_VALUE
typedef int BOOL;
#ifndef FALSE
#define FALSE 0
-#endif // FALSE
+#endif // !FALSE
#ifndef TRUE
#define TRUE 1
-#endif // TRUE
-typedef unsigned int u_int;
-typedef unsigned char BYTE;
-typedef unsigned short WORD;
-typedef unsigned long DWORD;
-typedef BYTE BOOLEAN;
-#endif // _WIN32
-
+#endif // !TRUE
+typedef unsigned int u_int;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int DWORD;
+typedef BYTE BOOLEAN;
+#endif // !_WIN32
+
+// Might depend on the platform...
+#ifndef DISABLE_UINT8_16_32_TYPEDEF
typedef unsigned char uint8;
typedef unsigned short uint16;
-typedef unsigned int uint32; // Might be unsigned long...
+typedef unsigned int uint32;
+#endif // !DISABLE_UINT8_16_32_TYPEDEF
// Conflict with OpenCV...
#ifdef ENABLE_INT64_TYPEDEF
@@ -330,53 +355,47 @@ typedef uint64_t uint64;
#endif // defined(_MSC_VER) || defined(__BORLANDC__)
#endif // ENABLE_INT64_TYPEDEF
-// Might vary also and should be moved elsewhere...
-union uShort
-{
- uint16 v;
- uint8 c[2];
-};
-typedef union uShort uShort;
-
-union uLong
-{
- long v;
- uint8 c[4];
-};
-typedef union uLong uLong;
-
-union uFloat
-{
- float v;
- uint8 c[4];
-};
-typedef union uFloat uFloat;
+#ifndef DISABLE_OLD_MSC_VER_INT_T_TYPEDEF
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#if _MSC_VER >= 1600
+#else
+typedef __int8 int8_t;
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#endif // _MSC_VER >= 1600
+#endif // defined(_MSC_VER) || defined(__BORLANDC__)
+#endif // !DISABLE_OLD_MSC_VER_INT_T_TYPEDEF
#ifndef _WIN32
typedef union _LARGE_INTEGER {
struct {
- unsigned long LowPart;
- long HighPart;
+ unsigned int LowPart;
+ int HighPart;
};
struct {
- unsigned long LowPart;
- long HighPart;
+ unsigned int LowPart;
+ int HighPart;
} u;
long long QuadPart;
} LARGE_INTEGER;
typedef union _ULARGE_INTEGER {
struct {
- unsigned long LowPart;
- unsigned long HighPart;
+ unsigned int LowPart;
+ unsigned int HighPart;
};
struct {
- unsigned long LowPart;
- unsigned long HighPart;
+ unsigned int LowPart;
+ unsigned int HighPart;
} u;
unsigned long long QuadPart;
} ULARGE_INTEGER;
-#endif // _WIN32
+#endif // !_WIN32
/*
Structure corresponding to a color in a RGB format (red, green and blue
@@ -410,6 +429,37 @@ inline RGBCOLOR rgbcolor(UCHAR r, UCHAR g, UCHAR b)
# endif // INIT_DEBUG
#endif // defined(_MSC_VER) && defined(_DEBUG) && !defined(DISABLE_ADDITIONAL_DEBUG_FEATURES)
+#ifndef DISABLE_USE_SNPRINTF
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#define snprintf c99_snprintf
+#define vsnprintf c99_vsnprintf
+
+__inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
+{
+ int count = -1;
+
+ if (size != 0)
+ count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
+ if (count == -1)
+ count = _vscprintf(format, ap);
+
+ return count;
+}
+
+__inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
+{
+ int count;
+ va_list ap;
+
+ va_start(ap, format);
+ count = c99_vsnprintf(outBuf, size, format, ap);
+ va_end(ap);
+
+ return count;
+}
+#endif // defined(_MSC_VER) && _MSC_VER < 1900
+#endif // DISABLE_USE_SNPRINTF
+
/*
enum EXIT_CODE
{
@@ -426,15 +476,16 @@ enum EXIT_CODE
#define EXIT_NAME_TOO_LONG 5
#define EXIT_OUT_OF_MEMORY 6
#define EXIT_OBJECT_NONSIGNALED 7
-#define EXIT_KILLED_THREAD 8
-#define EXIT_CANCELED_THREAD 9
-#define EXIT_IO_PENDING 10
-#define EXIT_KILLED_PROCESS 11
-#define EXIT_CHANGED 12
-#define EXIT_NOT_CHANGED 13
-#define EXIT_FOUND 14
-#define EXIT_NOT_FOUND 15
-#define EXIT_NOT_IMPLEMENTED 16
+#define EXIT_TOO_MANY_SEMAPHORES 8
+#define EXIT_KILLED_THREAD 9
+#define EXIT_CANCELED_THREAD 10
+#define EXIT_IO_PENDING 11
+#define EXIT_KILLED_PROCESS 12
+#define EXIT_CHANGED 13
+#define EXIT_NOT_CHANGED 14
+#define EXIT_FOUND 15
+#define EXIT_NOT_FOUND 16
+#define EXIT_NOT_IMPLEMENTED 17
// Strings corresponding to the previous return values.
EXTERN_C const char* szOSUtilsErrMsgs[];
@@ -486,8 +537,8 @@ EXTERN_C char* FormatLastErrorMsg(char* buf, int buflen);
#ifdef __GNUC__
// Disable some GCC warnings.
-#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic push
#endif // (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
#endif // __GNUC__
@@ -512,8 +563,6 @@ EXTERN_C char* FormatLastErrorMsg(char* buf, int buflen);
// Restore the GCC warnings previously disabled.
#if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
#pragma GCC diagnostic pop
-#else
-#pragma GCC diagnostic warning "-Wunused-but-set-variable"
#endif // (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
#endif // __GNUC__
@@ -604,4 +653,4 @@ Debug macros specific to OSCore.
# define PRINT_DEBUG_ERROR_OSCORE(params)
#endif // _DEBUG_ERRORS_OSCORE
-#endif // OSCORE_H
+#endif // !OSCORE_H
diff --git a/CamSvcSrv/jni/OSCriticalSection.h b/CamSvcSrv/jni/OSCriticalSection.h
index f2b70b3..1a913b1 100644
--- a/CamSvcSrv/jni/OSCriticalSection.h
+++ b/CamSvcSrv/jni/OSCriticalSection.h
@@ -81,7 +81,7 @@ inline int InitCriticalSection(CRITICAL_SECTION* pCriticalSection)
}
#else
InitializeCriticalSection(pCriticalSection);
-#endif // WINCE
+#endif // !WINCE
#else
pthread_mutexattr_t attr;
@@ -148,7 +148,7 @@ inline void DeleteCriticalSection(CRITICAL_SECTION* pCriticalSection)
pCriticalSection));
}
}
-#endif // _WIN32
+#endif // !_WIN32
#ifndef _WIN32
/*
@@ -170,7 +170,7 @@ inline void EnterCriticalSection(CRITICAL_SECTION* pCriticalSection)
pCriticalSection));
}
}
-#endif // _WIN32
+#endif // !_WIN32
#ifndef _WIN32
/*
@@ -203,7 +203,7 @@ inline BOOL TryEnterCriticalSection(CRITICAL_SECTION* pCriticalSection)
return TRUE;
}
-#endif // _WIN32
+#endif // !_WIN32
#ifndef _WIN32
/*
@@ -229,7 +229,7 @@ inline void LeaveCriticalSection(CRITICAL_SECTION* pCriticalSection)
pCriticalSection));
}
}
-#endif // _WIN32
+#endif // !_WIN32
/*
Thread-safe version of memcpy. Wait for ownership of the specified critical section object
@@ -256,4 +256,4 @@ inline void memcpy_ts(void* pDest, void* pSrc, size_t Size, CRITICAL_SECTION* pC
LeaveCriticalSection(pCriticalSection);
}
-#endif // OSCRITICALSECTION_H
+#endif // !OSCRITICALSECTION_H
diff --git a/CamSvcSrv/jni/OSMisc.c b/CamSvcSrv/jni/OSMisc.c
index 9d48a6b..81bee07 100644
--- a/CamSvcSrv/jni/OSMisc.c
+++ b/CamSvcSrv/jni/OSMisc.c
@@ -5,8 +5,6 @@ OSMisc.c
Miscellaneous things.
Fabrice Le Bars
-mean() and var() from Guillaume Brosse and Antone Borissov
-fgets2() by Luc Jaulin
Created : 2009-01-28
@@ -23,6 +21,17 @@ Created : 2009-01-28
#include "OSMisc.h"
+// Need to be undefined at the end of the file...
+// min and max might cause incompatibilities with GCC...
+#ifndef _MSC_VER
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif // !max
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif // !min
+#endif // !_MSC_VER
+
#ifndef DISABLE_USER_INPUT_FUNCTIONS
#ifndef DISABLE_USER_INPUT_TIMEOUT_FUNCTIONS
//// From olsrd...
@@ -304,7 +313,7 @@ char GetUserInputTimeout(UINT timeout)
return buf[0];
#endif // _WIN32
}
-#endif // DISABLE_USER_INPUT_TIMEOUT_FUNCTIONS
+#endif // !DISABLE_USER_INPUT_TIMEOUT_FUNCTIONS
/*
Prompt for the user to press any key.
@@ -577,7 +586,7 @@ void WaitForUserInput(void)
#endif // _WIN32
#endif //USE_PAUSE_CMD
}
-#endif // DISABLE_USER_INPUT_FUNCTIONS
+#endif // !DISABLE_USER_INPUT_FUNCTIONS
/*
Allocate memory for an array of height*width and initialize it to 0.
@@ -733,3 +742,13 @@ void free_array3(void*** p, int height, int width)
}
free(p); p = NULL;
}
+
+// min and max might cause incompatibilities with GCC...
+#ifndef _MSC_VER
+#ifdef max
+#undef max
+#endif // max
+#ifdef min
+#undef min
+#endif // min
+#endif // !_MSC_VER
diff --git a/CamSvcSrv/jni/OSMisc.h b/CamSvcSrv/jni/OSMisc.h
index 5ef1dda..28b108f 100644
--- a/CamSvcSrv/jni/OSMisc.h
+++ b/CamSvcSrv/jni/OSMisc.h
@@ -5,8 +5,6 @@ OSMisc.h
Miscellaneous things.
Fabrice Le Bars
-mean() and var() from Guillaume Brosse and Antone Borissov
-fgets2() by Luc Jaulin
Created : 2009-01-28
@@ -34,8 +32,8 @@ Created : 2009-01-28
#ifndef DISABLE_USER_INPUT_FUNCTIONS
#ifndef DISABLE_USER_INPUT_TIMEOUT_FUNCTIONS
#include "OSTime.h"
-#endif // DISABLE_USER_INPUT_TIMEOUT_FUNCTIONS
-#endif // DISABLE_USER_INPUT_FUNCTIONS
+#endif // !DISABLE_USER_INPUT_TIMEOUT_FUNCTIONS
+#endif // !DISABLE_USER_INPUT_FUNCTIONS
/*
Debug macros specific to OSMisc.
@@ -73,9 +71,26 @@ Debug macros specific to OSMisc.
#ifndef DISABLE_USER_INPUT_FUNCTIONS
#ifdef _WIN32
#else
+#ifndef DISABLE_CUSTOM_BAUDRATE
+#ifdef __linux__
+#pragma push_macro("termios")
+#undef termios
+#define termios termbits_termios
+#include // Not compatible with termios.h, see https://stackoverflow.com/questions/37710525/including-termios-h-and-asm-termios-h-in-the-same-project...
+#undef termios
+#pragma pop_macro("termios")
+#endif // __linux__
+#endif // !DISABLE_CUSTOM_BAUDRATE
#include
#endif // _WIN32
-#endif // DISABLE_USER_INPUT_FUNCTIONS
+#endif // !DISABLE_USER_INPUT_FUNCTIONS
+
+#ifndef DISABLE_REBOOT_FUNCTIONS
+#ifdef _WIN32
+#else
+#include
+#endif // _WIN32
+#endif // !DISABLE_REBOOT_FUNCTIONS
//// To check...
//#ifdef __GNUC__
@@ -85,6 +100,17 @@ Debug macros specific to OSMisc.
//#define strnicmp _strnicmp
//#endif // __GNUC__
+// Need to be undefined at the end of the file...
+// min and max might cause incompatibilities with GCC...
+#ifndef _MSC_VER
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif // !max
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif // !min
+#endif // !_MSC_VER
+
#define MAX_BUF_LEN 256
#define MAX_TIMEOUT_PROMPTGETUSERINPUTTIMEOUT 25500
@@ -93,6 +119,8 @@ Debug macros specific to OSMisc.
#define KELVIN2CELSIUS(temperature) ((temperature)-273.15)
#define CELSIUS2KELVIN(temperature) ((temperature)+273.15)
+#define STANDARD_GRAVITY 9.80665
+
// Earth radius in m.
#define EARTH_RADIUS 6371000
@@ -100,6 +128,107 @@ Debug macros specific to OSMisc.
#define NORTH_EAST_DOWN_COORDINATE_SYSTEM 1
#define NORTH_WEST_UP_COORDINATE_SYSTEM 2
+#ifndef SQR_DEFINED
+#define SQR_DEFINED
+#ifndef sqr
+/*
+Compute the square of a value.
+
+double x : (IN) Value.
+
+Return : The square of x.
+*/
+inline double sqr(double x)
+{
+ return x*x;
+}
+#endif // !sqr
+#endif // !SQR_DEFINED
+
+#ifndef sq
+#define sq(x) ((x)*(x))
+#endif // !sq
+
+#ifndef SIGN_DEFINED
+#define SIGN_DEFINED
+#ifndef sign
+/*
+Return +1 if x is positive, -1 if x is negative or x/epsilon if x is between -epsilon and epsilon.
+
+double x : (IN) Value.
+double epsilon : (IN) Threshold.
+
+Return : +1, -1 or x/epsilon.
+*/
+inline double sign(double x, double epsilon)
+{
+ if (x >= epsilon)
+ return 1;
+ else if (x <= -epsilon)
+ return -1;
+ else if (epsilon == 0)
+ return 0;
+ else
+ return x/epsilon;
+}
+#endif // !sign
+#endif // !SIGN_DEFINED
+
+#ifndef constrain
+#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
+#endif // !constrain
+
+// See https://www.arduino.cc/reference/en/language/functions/math/map/.
+inline double remap2range(double x, double in_min, double in_max, double out_min, double out_max)
+{
+ return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
+}
+
+inline double quantification(double v, double step)
+{
+ //double q = 0;
+ //q = q >= 0? floor(v/step+0.5): ceil(v/step-0.5);
+ //q = q*step;
+ return floor(v/step+0.5)*step;
+}
+
+// In rad.
+inline void quaternion2euler(double qw, double qx, double qy, double qz, double* pRoll, double* pPitch, double* pYaw)
+{
+ *pRoll = atan2(2*qy*qz+2*qw*qx, 2*sqr(qw)+2*sqr(qz)-1);
+ *pPitch = -asin(constrain(2*qx*qz-2*qw*qy, -1, 1)); // Attempt to avoid potential NAN...
+ *pYaw = atan2(2*qx*qy+2*qw*qz, 2*sqr(qw)+2*sqr(qx)-1);
+}
+
+// In rad.
+inline void euler2quaternion(double roll, double pitch, double yaw, double* pQw, double* pQx, double* pQy, double* pQz)
+{
+ double t0 = cos(yaw * 0.5);
+ double t1 = sin(yaw * 0.5);
+ double t2 = cos(roll * 0.5);
+ double t3 = sin(roll * 0.5);
+ double t4 = cos(pitch * 0.5);
+ double t5 = sin(pitch * 0.5);
+ *pQw = t0 * t2 * t4 + t1 * t3 * t5;
+ *pQx = t0 * t3 * t4 - t1 * t2 * t5;
+ *pQy = t0 * t2 * t5 + t1 * t3 * t4;
+ *pQz = t1 * t2 * t4 - t0 * t3 * t5;
+}
+
+/*
+Get the depth from the pressure (pressure difference = density x g x height).
+
+double pressure : (IN) Pressure in bar.
+double pressureref : (IN) Pressure at the surface in bar, used as reference (e.g. 1).
+double density : (IN) Water density in kg/m3 (e.g. 1000).
+
+Return : The depth in m.
+*/
+inline double Pressure2Height(double pressure, double pressureref, double density)
+{
+ return -(pressure-pressureref)*1e5/(density*STANDARD_GRAVITY);
+}
+
/*
Return an angle between 0 and 2*M_PI.
@@ -196,53 +325,9 @@ inline double fmod_2PI_deg2rad(double theta)
return fmod(fmod(theta*M_PI/180.0, 2*M_PI)+3*M_PI, 2*M_PI)-M_PI;
}
-inline double quantification(double v, double step)
-{
- //double q = 0;
- //q = q >= 0? floor(v/step+0.5): ceil(v/step-0.5);
- //q = q*step;
- return floor(v/step+0.5)*step;
-}
-
-#ifndef SQR_DEFINED
-#define SQR_DEFINED
-/*
-Compute the square of a value.
-
-double x : (IN) Value.
-
-Return : The square of x.
-*/
-inline double sqr(double x)
-{
- return x*x;
-}
-#endif // SQR_DEFINED
-
-#ifndef SIGN_DEFINED
-#define SIGN_DEFINED
-/*
-Return x/epsilon if x is between -epsilon and epsilon or -1 if x is negative,
-+1 if x is positive.
-
-double x : (IN) Value.
-double epsilon : (IN) Threshold.
-
-Return : -1, +1 or x/epsilon.
-*/
-inline double sign(double x, double epsilon)
-{
- if (x >= epsilon)
- return 1;
- else if (x <= -epsilon)
- return -1;
- else
- return x/epsilon;
-}
-#endif // SIGN_DEFINED
-
#ifndef MEAN_DEFINED
#define MEAN_DEFINED
+#ifndef mean
/*
Compute the mean of a table.
@@ -264,10 +349,12 @@ inline double mean(double* tab, int tab_length)
return m;
}
-#endif // MEAN_DEFINED
+#endif // !mean
+#endif // !MEAN_DEFINED
#ifndef VAR_DEFINED
#define VAR_DEFINED
+#ifndef var
/*
Compute the variance of a table.
@@ -295,7 +382,8 @@ inline double var(double* tab, int tab_length)
return v;
}
-#endif // VAR_DEFINED
+#endif // !var
+#endif // !VAR_DEFINED
/*
Compute the mean of a table using a table of numbers of occurences for each value.
@@ -355,11 +443,84 @@ inline double varn(double* tab_values, double* tab_numbers, int tab_length)
return v;
}
+// https://en.wikiversity.org/wiki/C_Source_Code/Find_the_median_and_mean
+// https://www.tutorialspoint.com/learn_c_by_examples/median_program_in_c.htm
+inline double median(double* tab_values, int tab_length)
+{
+ double temp = 0;
+ int i = 0, j = 0;
+ int n = tab_length;
+ double* x = tab_values;
+
+ // The following two loops sort the array x in ascending order.
+ for (i = 0; i < n-1; i++) {
+ for (j = i+1; j < n; j++) {
+ if (x[j] < x[i]) {
+ // Swap elements.
+ temp = x[i];
+ x[i] = x[j];
+ x[j] = temp;
+ }
+ }
+ }
+
+ return x[n/2];
+}
+
+// https://en.wikiversity.org/wiki/C_Source_Code/Find_the_median_and_mean
+// https://www.tutorialspoint.com/learn_c_by_examples/median_program_in_c.htm
+inline double median2(double* tab_values, int tab_length)
+{
+ double temp = 0;
+ int i = 0, j = 0;
+ int n = tab_length;
+ double* x = tab_values;
+
+ // The following two loops sort the array x in ascending order.
+ for (i = 0; i < n-1; i++) {
+ for (j = i+1; j < n; j++) {
+ if (x[j] < x[i]) {
+ // Swap elements.
+ temp = x[i];
+ x[i] = x[j];
+ x[j] = temp;
+ }
+ }
+ }
+
+ if (n%2 == 0)
+ {
+ // For an even number of elements, return the mean of the two elements in the middle.
+ return ((x[n/2]+x[n/2-1])/2.0);
+ }
+ else
+ {
+ // Return the element in the middle.
+ return x[n/2];
+ }
+}
+
+// https://fr.wikipedia.org/wiki/Moyenne_mobile
+// https://en.wikipedia.org/wiki/Moving_average
+// http://www.cafemath.fr/mathblog/article.php?page=MovingAverages.php
+inline double rect_mv_avg(double newvalue, double oldestvalue, double prevaverage, int n)
+{
+ return prevaverage+(newvalue-oldestvalue)/(double)n;
+}
+
+// https://fr.wikipedia.org/wiki/Moyenne_mobile
+// https://en.wikipedia.org/wiki/Moving_average
+// http://www.cafemath.fr/mathblog/article.php?page=MovingAverages.php
+inline double exp_mv_avg(double newvalue, double prevaverage, double alpha)
+{
+ return alpha*prevaverage+(1.0-alpha)*newvalue;
+}
+
#ifndef FGETS2_DEFINED
#define FGETS2_DEFINED
/*
Return a line of a file using fgets(), skipping lines that begin with a '%'.
-Return NULL when a line begin with a '$' or when fgets() return NULL.
+Return NULL when a line begins with a '$' or when fgets() returns NULL.
FILE* file : (IN) Pointer to a file.
char* line : (IN) Storage location for data.
@@ -384,13 +545,13 @@ inline char* fgets2(FILE* file, char* line, int nbChar)
return r;
}
-#endif // FGETS2_DEFINED
+#endif // !FGETS2_DEFINED
/*
Return a line of a file using fgets(), skipping lines that begin with a '%'
(Scilab-style comments), a '#' (Linux configuration files-style comments) or
"//" (C-style comments).
-Return NULL when a line begin with a '$' or when fgets() return NULL, or if
+Return NULL when a line begins with a '$' or when fgets() returns NULL, or if
the maximum number of characters to read is less than 2.
FILE* file : (IN) Pointer to a file.
@@ -426,6 +587,91 @@ inline char* fgets3(FILE* file, char* line, int nbChar)
return r;
}
+/*
+Return a line of a file using fgets(), skipping lines that begin with a '%'
+(Scilab-style comments), a '#' (Linux configuration files-style comments) or
+"//" (C-style comments).
+Return NULL when fgets() returns NULL, or if
+the maximum number of characters to read is less than 2.
+
+FILE* file : (IN) Pointer to a file.
+char* line : (IN) Storage location for data.
+int nbChar : (IN) Maximum number of characters to read.
+
+Return : The line or NULL.
+*/
+inline char* fgets4(FILE* file, char* line, int nbChar)
+{
+ char* r = NULL;
+
+ if (nbChar < 2)
+ {
+ return NULL;
+ }
+
+ do
+ {
+ r = fgets(line, nbChar, file);
+ }
+ while ((
+ (line[0] == '%')||
+ (line[0] == '#')||
+ ((line[0] == '/')&&(line[1] == '/'))
+ ) && (r != NULL));
+
+ return r;
+}
+
+/*
+Return a line from an input file using fgets(), skipping lines that begin with a '%'
+(Scilab-style comments), a '#' (Linux configuration files-style comments) or
+"//" (C-style comments).
+Return NULL when a line begins with a '$' or when fgets() returns NULL, or if
+the maximum number of characters to read is less than 2.
+All the skipped lines are saved to the output file.
+
+FILE* filein : (IN) Pointer to an input file.
+FILE* fileout : (IN) Pointer to an output file.
+char* line : (IN) Storage location for data.
+int nbChar : (IN) Maximum number of characters to read.
+
+Return : The line or NULL.
+*/
+inline char* fgetscopy3(FILE* filein, FILE* fileout, char* line, int nbChar)
+{
+ char* r = NULL;
+
+ if (nbChar < 2)
+ {
+ return NULL;
+ }
+
+ for (;;)
+ {
+ r = fgets(line, nbChar, filein);
+ if ((
+ (line[0] == '%')||
+ (line[0] == '#')||
+ ((line[0] == '/')&&(line[1] == '/'))
+ ) && (r != NULL))
+ {
+ if (fprintf(fileout, "%s", line) < 0) return NULL;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (line[0] == '$')
+ {
+ if (r != NULL) fprintf(fileout, "%s", line);
+ r = NULL;
+ }
+
+ return r;
+}
+
/*
Return : The current line number or -1 if an error occurs.
*/
@@ -671,6 +917,9 @@ inline int fcopy(char* szFromFilePath, char* szToFilePath, size_t* pBytesCopied)
inline void RemoveExtensionInFilePath(char* szFilePath)
{
+ // WIN32_WINNT 0x0602 : PathCchRemoveExtension
+ // WIN32 : PathRemoveExtension
+
int idx = 0;
for (idx = (int)strlen(szFilePath)-1; idx >= 0; idx--) { if (szFilePath[idx] == '.') break; }
@@ -693,11 +942,251 @@ inline void RemovePathInFilePath(char* szFilePath)
if ((bFound)&&(idx >= 0)&&(idx < (int)strlen(szFilePath)-1)) memmove(szFilePath, szFilePath+idx+1, strlen(szFilePath)-idx);
}
+inline void GetFileNameAndFilePathAndChangeExtension(char* szFileInPath, char* szNewExtension, char* szFileOutPath, char* szFileOutName)
+{
+ // WIN32_WINNT 0x0602 : PathCchRenameExtension
+ // WIN32 : PathRenameExtension
+
+ strcpy(szFileOutPath, szFileInPath);
+ RemoveExtensionInFilePath(szFileOutPath);
+ strcpy(szFileOutName, szFileOutPath);
+ strcat(szFileOutPath, szNewExtension);
+ RemovePathInFilePath(szFileOutName);
+}
+
+#ifndef STRISTR_DEFINED
+#define STRISTR_DEFINED
+// From the Snippets collection SNIP9707.ZIP...
+inline char* stristr(char* String, char* Pattern)
+{
+ char* pptr = NULL;
+ char* sptr = NULL;
+ char* start = NULL;
+
+ for (start = (char*)String; *start != 0; start++)
+ {
+ // Find start of pattern in string.
+ for (; ((*start != 0) && (toupper(*start)!= toupper(*Pattern))); start++)
+ ;
+ if (0 == *start)
+ return NULL;
+
+ pptr = (char*)Pattern;
+ sptr = (char*)start;
+
+ while (toupper(*sptr) == toupper(*pptr))
+ {
+ sptr++;
+ pptr++;
+
+ // If end of pattern then pattern was found.
+
+ if (0 == *pptr)
+ return (start);
+ }
+ }
+
+ return NULL;
+}
+#endif // !STRISTR_DEFINED
+
+// *pOut of length *pOutstrlen will not contain beginpattern nor endpattern...
+inline char* strstrbeginend(char* str, char* beginpattern, char* endpattern, char** pOut, int* pOutstrlen)
+{
+ char* ptr = NULL;
+ char* ptr2 = NULL;
+
+ ptr = strstr(str, beginpattern);
+ if (ptr == NULL)
+ {
+ *pOut = NULL;
+ *pOutstrlen = 0;
+ return NULL;
+ }
+ ptr2 = strstr(ptr+strlen(beginpattern), endpattern);
+ if (ptr2 == NULL)
+ {
+ *pOut = NULL;
+ *pOutstrlen = 0;
+ return NULL;
+ }
+ *pOutstrlen = (int)(ptr2-(ptr+strlen(beginpattern)));
+ if (*pOutstrlen < 0)
+ {
+ *pOut = NULL;
+ *pOutstrlen = 0;
+ return NULL;
+ }
+ *pOut = ptr+strlen(beginpattern);
+
+ return *pOut;
+}
+
+// *pOut of length *pOutstrlen will not contain beginpattern nor endpattern...
+inline char* stristrbeginend(char* str, char* beginpattern, char* endpattern, char** pOut, int* pOutstrlen)
+{
+ char* ptr = NULL;
+ char* ptr2 = NULL;
+
+ ptr = stristr(str, beginpattern);
+ if (ptr == NULL)
+ {
+ *pOut = NULL;
+ *pOutstrlen = 0;
+ return NULL;
+ }
+ ptr2 = stristr(ptr+strlen(beginpattern), endpattern);
+ if (ptr2 == NULL)
+ {
+ *pOut = NULL;
+ *pOutstrlen = 0;
+ return NULL;
+ }
+ *pOutstrlen = (int)(ptr2-(ptr+strlen(beginpattern)));
+ if (*pOutstrlen < 0)
+ {
+ *pOut = NULL;
+ *pOutstrlen = 0;
+ return NULL;
+ }
+ *pOut = ptr+strlen(beginpattern);
+
+ return *pOut;
+}
+
+// Reverse search : the last occurence will be returned.
+// *pOut of length *pOutstrlen will not contain beginpattern nor endpattern...
+inline char* rstrstrbeginend(char* str, char* beginpattern, char* endpattern, char** pOut, int* pOutstrlen)
+{
+ *pOut = NULL;
+ *pOutstrlen = 0;
+ for (;;)
+ {
+ int plen = 0;
+ char* p = strstrbeginend(str, beginpattern, endpattern, &p, &plen);
+ if (p == NULL)
+ break;
+ *pOut = p;
+ *pOutstrlen = plen;
+ str = p-strlen(beginpattern)+1;
+ }
+
+ return *pOut;
+}
+
+// Reverse search : the last occurence will be returned.
+// *pOut of length *pOutstrlen will not contain beginpattern nor endpattern...
+inline char* rstristrbeginend(char* str, char* beginpattern, char* endpattern, char** pOut, int* pOutstrlen)
+{
+ *pOut = NULL;
+ *pOutstrlen = 0;
+ for (;;)
+ {
+ int plen = 0;
+ char* p = stristrbeginend(str, beginpattern, endpattern, &p, &plen);
+ if (p == NULL)
+ break;
+ *pOut = p;
+ *pOutstrlen = plen;
+ str = p-strlen(beginpattern)+1;
+ }
+
+ return *pOut;
+}
+
inline double sensor_err(double bias_err, double max_rand_err)
{
return bias_err+max_rand_err*(2.0*rand()/(double)RAND_MAX-1.0);
}
+// Remember to reset *pipsi to 0 whenever this control is re-enabled.
+// direction_coef : depending on the type of robot, we need to invert depending on the direction of the movement,
+// set to -1 if needed or 1 otherwise.
+inline double PID_angle_control(double psi_bar, double psi_bar_prev, double psi, double omega, double* pipsi, double direction_coef, double dt,
+ double Kp, double Kd, double Ki, double up_max, double ud_max, double ui_max,
+ double u_min, double u_max, double error_min, double error_max, double omega_max)
+{
+ double u = 0;
+ double error = fmod_2PI(psi_bar-psi);
+ double derivative = -omega;
+ double integral = *pipsi;
+ if (psi_bar != psi_bar_prev) integral = 0;
+ if (error > error_max)
+ {
+ u = sign(direction_coef, 0)*u_max;
+ integral = 0;
+ }
+ else if (error < error_min)
+ {
+ u = sign(direction_coef, 0)*u_min;
+ integral = 0;
+ }
+ else
+ {
+ if (fabs(Kp*error/M_PI) > up_max) u += sign(direction_coef, 0)*sign(Kp*error/M_PI, 0)*up_max;
+ else u += sign(direction_coef, 0)*Kp*error/M_PI; // /M_PI to try to normalize...
+ if (fabs(Kd*derivative/omega_max) > ud_max) u += sign(direction_coef, 0)*sign(Kd*derivative/omega_max, 0)*ud_max;
+ else u += sign(direction_coef, 0)*Kd*derivative/omega_max; // /omegaz_max to try to normalize...
+ if (fabs(Ki*integral/M_PI) > ui_max) u += sign(direction_coef, 0)*sign(Ki*integral/M_PI, 0)*ui_max;
+ else u += sign(direction_coef, 0)*Ki*integral/M_PI; // /M_PI to try to normalize...
+ integral = integral+error*dt;
+ }
+ u = (u < u_min)? u_min: ((u > u_max)? u_max: u);
+ *pipsi = integral;
+ return u;
+}
+
+// Remember to reset *piz to 0 whenever this control is re-enabled.
+// direction_coef : depending on the type of robot, we need to invert depending on the direction of the movement,
+// set to -1 if needed or 1 otherwise.
+inline double PID_control(double z_bar, double z_bar_prev, double z, double dz, double* piz, double direction_coef, double dt,
+ double Kp, double Kd, double Ki, double up_max, double ud_max, double ui_max,
+ double u_min, double u_max, double error_min, double error_max, double dz_max)
+{
+ double u = 0;
+ double error = z_bar-z;
+ double derivative = -dz;
+ double integral = *piz;
+ if (z_bar != z_bar_prev) integral = 0;
+ if (error > error_max)
+ {
+ u = sign(direction_coef, 0)*u_max;
+ integral = 0;
+ }
+ else if (error < error_min)
+ {
+ u = sign(direction_coef, 0)*u_min;
+ integral = 0;
+ }
+ else
+ {
+ if (fabs(Kp*error) > up_max) u += sign(direction_coef, 0)*sign(Kp*error, 0)*up_max;
+ else u += sign(direction_coef, 0)*Kp*error;
+ if (fabs(Kd*derivative/dz_max) > ud_max) u += sign(direction_coef, 0)*sign(Kd*derivative/dz_max, 0)*ud_max;
+ else u += sign(direction_coef, 0)*Kd*derivative/dz_max; // /dz_max to try to normalize...
+ if (fabs(Ki*integral) > ui_max) u += sign(direction_coef, 0)*sign(Ki*integral, 0)*ui_max;
+ else u += sign(direction_coef, 0)*Ki*integral;
+ integral = integral+error*dt;
+ }
+ u = (u < u_min)? u_min: ((u > u_max)? u_max: u);
+ *piz = integral;
+ return u;
+}
+
+// Return theta_star (see http://www.ensta-bretagne.fr/jaulin/paper_jaulin_irsc12.pdf).
+// Remember to reset *pie to 0 if this control has been disabled during some time...
+inline double LineFollowing_integral(double phi, double phi_prev, double e, double* pie, double gamma_infinite, double r, double Ki, double integral_max, double dt)
+{
+ double psi_star = 0;
+ double integral = *pie;
+ if (phi != phi_prev) integral = 0;
+ if (fabs(Ki*integral) > integral_max) psi_star = phi-(2.0*gamma_infinite/M_PI)*atan2((e+sign(Ki*integral, 0)*integral_max),r);
+ else psi_star = phi-(2.0*gamma_infinite/M_PI)*atan2((e+Ki*integral),r);
+ integral = integral+e*dt;
+ *pie = integral;
+ return psi_star;
+}
+
// Return theta_star (see http://www.ensta-bretagne.fr/jaulin/paper_jaulin_irsc12.pdf).
inline double LineFollowing(double phi, double e, double gamma_infinite, double r)
{
@@ -890,6 +1379,32 @@ inline void RefCoordSystem2GPS(double lat0, double long0, double alt0,
}
}
+inline double longitude180handling(double long0, double longa, double longb, double longitude)
+{
+ if ((((longa >= 90)&&(longa <= 180))&&((longb >= -180)&&(longb <= -90)))||
+ (((longb >= 90)&&(longb <= 180))&&((longa >= -180)&&(longa <= -90))))
+ {
+ if (long0 >= 0)
+ {
+ if (longitude < 0) return longitude+360;
+ }
+ else
+ {
+ if (longitude > 0) return longitude-360;
+ }
+ }
+ return longitude;
+}
+
+inline void LineGPS2RefCoordSystem(double lat0, double long0, double alt0,
+ double lata, double longa, double alta, double latb, double longb, double altb,
+ double* pax, double* pay, double* paz, double* pbx, double* pby, double* pbz,
+ int cstype)
+{
+ GPS2RefCoordSystem(lat0, long0, alt0, lata, longitude180handling(long0, longa, longb, longa), alta, pax, pay, paz, cstype);
+ GPS2RefCoordSystem(lat0, long0, alt0, latb, longitude180handling(long0, longa, longb, longb), altb, pbx, pby, pbz, cstype);
+}
+
// angle_env : Angle of the x axis of the environment coordinate system
// w.r.t. an East - North - Up coordinate system, should be set to 0 if no
// specific environment (i.e. an East - North - Up coordinate system)
@@ -1192,27 +1707,181 @@ inline void RGB2HSL_MSPaint(double red, double green, double blue, double* pH, d
if (maxval != minval)
{
- double rnorm = (maxval-red)/mdiff;
- double gnorm = (maxval-green)/mdiff;
- double bnorm = (maxval-blue)/mdiff;
- saturation = (luminance <= 0.5)?(mdiff/msum):(mdiff/(510.0-msum));
+ double tmp = 60.0/mdiff;
if (red == maxval)
- hue = 60.0*(6.0+bnorm-gnorm);
- if (green == maxval)
- hue = 60.0*(2.0+rnorm-bnorm);
- if (blue == maxval)
- hue = 60.0*(4.0+gnorm-rnorm);
- if (hue > 360.0)
- hue -= 360.0;
+ {
+ hue = (green-blue)*tmp;
+ if (hue < 0) hue += 360.0;
+ }
+ else if (green == maxval)
+ hue = (blue-red)*tmp+120.0;
+ else if (blue == maxval)
+ hue = (red-green)*tmp+240.0;
+ saturation = (luminance <= 0.5)? (mdiff/msum): (mdiff/(510.0-msum));
}
// Microsoft Paint limits for H,S,L are 0..240.
- *pH = hue*240.0/360.0;
- *pS = saturation*240.0;
+ *pH = hue*240.0/360.0;
+ *pS = saturation*240.0;
*pL = luminance*240.0;
}
+/*
+Convert from HSV to RGB.
+
+double hue : (IN) Hue between 0..240.
+double saturation : (IN) Saturation between 0..240.
+double value : (IN) Value between 0..240.
+double* pR : (OUT) Pointer to the red between 0..255.
+double* pG : (OUT) Pointer to the green between 0..255.
+double* pB : (OUT) Pointer to the blue between 0..255.
+
+Return : Nothing.
+*/
+inline void HSV2RGB_MSPaint_Fake(double hue, double saturation, double value, double* pR, double* pG, double* pB)
+{
+
+ // From https://fr.wikipedia.org/wiki/Teinte_Saturation_Valeur,
+ // https://en.wikipedia.org/wiki/HSL_and_HSV and https://stackoverflow.com/questions/51203917/math-behind-hsv-to-rgb-conversion-of-colors.
+
+ int ti = 0;
+ double l = 0, m = 0; //, f = 0, n = 0;
+
+ hue = hue*360.0/240.0;
+ saturation = saturation/240.0;
+ value = value/240.0;
+
+ ti = ((int)floor(hue/60.0))%6;
+ //f = (hue/60.0)-ti;
+ l = value*(1-saturation);
+ m = value*(1-saturation*fabs(fmod(hue/60.0, 2)-1));
+ //m = value*(1-f*saturation);
+ //n = value*(1-(1-f)*saturation);
+
+ switch (ti)
+ {
+ case 0:
+ *pR = value*255.0;
+ *pG = m*255.0; //*pG = n*255.0;
+ *pB = l*255.0;
+ break;
+ case 1:
+ *pR = m*255.0;
+ *pG = value*255.0;
+ *pB = l*255.0;
+ break;
+ case 2:
+ *pR = l*255.0;
+ *pG = value*255.0;
+ *pB = m*255.0; //*pB = n*255.0;
+ break;
+ case 3:
+ *pR = l*255.0;
+ *pG = m*255.0;
+ *pB = value*255.0;
+ break;
+ case 4:
+ *pR = m*255.0; //*pR = n*255.0;
+ *pG = l*255.0;
+ *pB = value*255.0;
+ break;
+ case 5:
+ *pR = value*255.0;
+ *pG = l*255.0;
+ *pB = m*255.0;
+ break;
+ default:
+ *pR = 0;
+ *pG = 0;
+ *pB = 0;
+ break;
+ }
+}
+
+/*
+Convert from RGB to HSV.
+
+double red : (IN) Red between 0..255.
+double green : (IN) Green between 0..255.
+double blue : (IN) Blue between 0..255.
+double* pH : (OUT) Pointer to the hue between 0..240.
+double* pS : (OUT) Pointer to the saturation between 0..240.
+double* pV : (OUT) Pointer to the value between 0..240.
+
+Return : Nothing.
+*/
+inline void RGB2HSV_MSPaint_Fake(double red, double green, double blue, double* pH, double* pS, double* pV)
+{
+
+ // From https://fr.wikipedia.org/wiki/Teinte_Saturation_Valeur.
+
+ double minval = min(red, min(green, blue));
+ double maxval = max(red, max(green, blue));
+ double mdiff = maxval-minval;
+ double hue = 0.0;
+ double saturation = (maxval == 0)? 0: (1-minval/maxval);
+ double value = maxval/255.0;
+
+ if (maxval != minval)
+ {
+ double tmp = 60.0/mdiff;
+ if (red == maxval)
+ {
+ hue = (green-blue)*tmp;
+ if (hue < 0) hue += 360.0;
+ }
+ else if (green == maxval)
+ hue = (blue-red)*tmp+120.0;
+ else if (blue == maxval)
+ hue = (red-green)*tmp+240.0;
+ }
+
+ *pH = hue*240.0/360.0;
+ *pS = saturation*240.0;
+ *pV = value*240.0;
+}
+
+#ifndef DISABLE_REBOOT_FUNCTIONS
+inline void RebootComputer(void)
+{
+#ifdef _WIN32
+
+ // https://docs.microsoft.com/fr-fr/windows/desktop/Shutdown/displaying-the-shutdown-dialog-box
+
+ HANDLE hToken; // handle to process token
+ TOKEN_PRIVILEGES tkp; // pointer to token structure
+
+ // Get the current process token handle so we can get shutdown privilege.
+ OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
+
+ // Get the LUID for shutdown privilege.
+ LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
+
+ tkp.PrivilegeCount = 1; // One privilege to set.
+ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ // Get shutdown privilege for this process.
+ AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
+
+ if (!InitiateSystemShutdown(NULL, NULL, 0, TRUE, TRUE))
+ {
+ PRINT_DEBUG_ERROR_OSMISC(("RebootComputer error (%s) : %s\n", strtime_m(), GetLastErrorMsg()));
+ }
+
+ // Disable shutdown privilege.
+ tkp.Privileges[0].Attributes = 0;
+ AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
+#else
+ sync();
+ if (reboot(RB_AUTOBOOT) < 0)
+ {
+ PRINT_DEBUG_ERROR_OSMISC(("RebootComputer error (%s) : %s\n", strtime_m(), GetLastErrorMsg()));
+ }
+#endif // _WIN32
+}
+#endif // !DISABLE_REBOOT_FUNCTIONS
+
/*
Wait for the user to press the ENTER key.
@@ -1266,7 +1935,7 @@ See also getch() or kbhit() functions (conio.h).
Return : Nothing.
*/
EXTERN_C void WaitForUserInput(void);
-#endif // WINCE
+#endif // !WINCE
/*
Allocate memory for an array of height*width and initialize it to 0.
@@ -1328,4 +1997,14 @@ inline void useless_function(int useless_param)
printf("This function is not so useless!\n");
}
-#endif // OSMISC_H
+// min and max might cause incompatibilities with GCC...
+#ifndef _MSC_VER
+#ifdef max
+#undef max
+#endif // max
+#ifdef min
+#undef min
+#endif // min
+#endif // !_MSC_VER
+
+#endif // !OSMISC_H
diff --git a/CamSvcSrv/jni/OSNet.c b/CamSvcSrv/jni/OSNet.c
index 7c7fa45..4109b44 100644
--- a/CamSvcSrv/jni/OSNet.c
+++ b/CamSvcSrv/jni/OSNet.c
@@ -46,4 +46,4 @@ THREAD_PROC_RETURN_VALUE handlecliThreadProc(void* pHandlecliThreadParam)
return 0;
}
-#endif // DISABLE_THREADS_OSNET
+#endif // !DISABLE_THREADS_OSNET
diff --git a/CamSvcSrv/jni/OSNet.h b/CamSvcSrv/jni/OSNet.h
index de87164..a80e240 100644
--- a/CamSvcSrv/jni/OSNet.h
+++ b/CamSvcSrv/jni/OSNet.h
@@ -26,7 +26,7 @@ Created : 2007
#include "OSTime.h"
#ifndef DISABLE_THREADS_OSNET
#include "OSThread.h"
-#endif // DISABLE_THREADS_OSNET
+#endif // !DISABLE_THREADS_OSNET
/*
Debug macros specific to OSNet.
@@ -78,11 +78,9 @@ Debug macros specific to OSNet.
#pragma warn -8004
#endif // __BORLANDC__
#include
-#if (_WIN32_WINNT <= 0x0500)
#include
+#if (_WIN32_WINNT <= 0x0500)
#include
-#else
-#include
#endif // (_WIN32_WINNT <= 0x0500)
//#include
#ifdef __BORLANDC__
@@ -94,6 +92,9 @@ Debug macros specific to OSNet.
#include
#include
#include
+#ifndef DISABLE_IOCTLSOCKET
+#include
+#endif // !DISABLE_IOCTLSOCKET
#include
#include
#include
@@ -102,7 +103,13 @@ Debug macros specific to OSNet.
#ifndef DEFAULT_SOCK_TIMEOUT
#define DEFAULT_SOCK_TIMEOUT 10000
-#endif // DEFAULT_SOCK_TIMEOUT
+#endif // !DEFAULT_SOCK_TIMEOUT
+
+#define OTHER_DEV_TYPE_OSNET 0
+#define TCP_CLIENT_DEV_TYPE_OSNET 1
+#define TCP_SERVER_DEV_TYPE_OSNET 2
+#define UDP_CLIENT_DEV_TYPE_OSNET 3
+#define UDP_SERVER_DEV_TYPE_OSNET 4
#ifdef _WIN32
/*
@@ -168,6 +175,9 @@ typedef int SOCKET;
#define SD_SEND SHUT_WR
#define SD_BOTH SHUT_RDWR
+#ifndef DISABLE_IOCTLSOCKET
+#define ioctlsocket ioctl
+#endif // !DISABLE_IOCTLSOCKET
#define closesocket(sock) close((sock))
#endif // _WIN32
@@ -237,7 +247,18 @@ inline int InitNet(void)
"WSAStartup failed. "));
return EXIT_FAILURE;
}
-#endif
+#else
+#ifndef DISABLE_IGNORE_SIGPIPE
+ // See https://stackoverflow.com/questions/17332646/server-dies-on-send-if-client-was-closed-with-ctrlc...
+ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
+ {
+ PRINT_DEBUG_WARNING_OSNET(("InitNet warning (%s) : %s"
+ "\n",
+ strtime_m(),
+ "signal failed. "));
+ }
+#endif // DISABLE_IGNORE_SIGPIPE
+#endif // _WIN32
return EXIT_SUCCESS;
}
@@ -339,7 +360,7 @@ Return : The socket created or INVALID_SOCKET if there is an error.
//SOCKET socket(int af, int type, int protocol);
/*
-Close an existing socket.
+Close an existing socket (defined as close() for Linux).
InitNet() must be called before using any network function.
SOCKET s : (IN) Socket to close.
@@ -386,16 +407,16 @@ at least one socket meets the specified criteria depending on timeout. Upon retu
are updated to reflect the subset of the sockets that meet the specified condition.
Macros to manipulate and check fd_set contents :
-FD_ZERO(*set)
+FD_ZERO(fd_set* set)
Initialize the set to the null set.
-FD_SET(s, *set)
+FD_SET(int s, fd_set* set)
Add socket s to set.
-FD_ISSET(s, *set)
+FD_ISSET(int s, fd_set* set)
Nonzero if s is a member of the set. Otherwise, 0.
-FD_CLR(s, *set)
+FD_CLR(int s, fd_set* set)
Remove the socket s from set.
Structure to define the timeout :
@@ -457,9 +478,9 @@ Return : EXIT_SUCCESS or SOCKET_ERROR if there is an error.
*/
//int connect(SOCKET s, struct sockaddr* name, int namelen);
-//int send(SOCKET s);
+//int send(SOCKET s, char* buf, int len, int flags);
-//int recv(SOCKET s);
+//int recv(SOCKET s, char* buf, int len, int flags);
/*
Usually used with UDP sockets.
@@ -488,8 +509,10 @@ On return it will contain the actual length in bytes of the address returned. NU
//int shutdown(SOCKET s);
+//int setsockopt(SOCKET s, int level, int optname, char *optval, int optlen);
+
/*
-Set timeout options for a given socket.
+Set timeout options for a socket.
SOCKET sock : (IN) Socket.
int timeout : (IN) Timeout in ms for send and recv (0 to disable timeouts).
@@ -549,6 +572,81 @@ inline int setsockettimeouts(SOCKET sock, int timeout)
return EXIT_SUCCESS;
}
+/*
+Set SO_REUSEADDR option for a socket.
+
+SOCKET sock : (IN) Socket.
+BOOL reuseaddr : (IN) 1 to enable SO_REUSEADDR, 0 to disable.
+
+Return : EXIT_SUCCESS or EXIT_FAILURE if there is an error.
+*/
+inline int setsocketreuseaddr(SOCKET sock, BOOL reuseaddr)
+{
+ int iOptVal = 0;
+ int iOptLen = 0;
+
+ iOptVal = (int)reuseaddr;
+ iOptLen = sizeof(int);
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&iOptVal, iOptLen) == SOCKET_ERROR)
+ {
+ PRINT_DEBUG_WARNING_OSNET(("setsocketreuseaddr warning (%s) : %s(sock=%d, reuseaddr=%d)\n",
+ strtime_m(),
+ "setsockopt failed. ",
+ (int)sock, (int)reuseaddr));
+ //return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+#ifndef DISABLE_IOCTLSOCKET
+/*
+Set blocking mode for a socket.
+
+SOCKET sock : (IN) Socket.
+BOOL blocking : (IN) 1 to make blocking, 0 to non-blocking.
+
+Return : EXIT_SUCCESS or EXIT_FAILURE if there is an error.
+*/
+inline int setsocketblocking(SOCKET sock, BOOL blocking)
+{
+#ifdef _WIN32
+ unsigned long blockingMode = (blocking? 0: 1);
+
+ if (ioctlsocket(sock, FIONBIO, &blockingMode) != NO_ERROR)
+ {
+ PRINT_DEBUG_ERROR_OSNET(("setsocketblocking error (%s) : (FIONBIO) %s(sock=%d, blocking=%d)\n",
+ strtime_m(),
+ WSAGetLastErrorMsg(),
+ (int)sock, (int)blocking));
+ return EXIT_FAILURE;
+ }
+#else
+ int flags = fcntl(sock, F_GETFL, 0);
+
+ if (flags == -1)
+ {
+ PRINT_DEBUG_ERROR_OSNET(("setsocketblocking error (%s) : (F_GETFL) %s(sock=%d, blocking=%d)\n",
+ strtime_m(),
+ WSAGetLastErrorMsg(),
+ (int)sock, (int)blocking));
+ return EXIT_FAILURE;
+ }
+ flags = (blocking? (flags&~O_NONBLOCK): (flags|O_NONBLOCK));
+ if (fcntl(sock, F_SETFL, flags) != 0)
+ {
+ PRINT_DEBUG_ERROR_OSNET(("setsocketblocking error (%s) : (F_SETFL) %s(sock=%d, blocking=%d)\n",
+ strtime_m(),
+ WSAGetLastErrorMsg(),
+ (int)sock, (int)blocking));
+ return EXIT_FAILURE;
+ }
+#endif // _WIN32
+
+ return EXIT_SUCCESS;
+}
+#endif // !DISABLE_IOCTLSOCKET
+
/*
Connect to an IPv4 TCP server.
@@ -611,8 +709,8 @@ inline int inittcpcli(SOCKET* pSock, char* address, char* port)
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = inet_addr(address);
sa.sin_port = htons((unsigned short)atoi(port));
+ sa.sin_addr.s_addr = inet_addr(address);
// Connect to server.
if (connect(*pSock, (struct sockaddr*)&sa, sizeof(sa)) != EXIT_SUCCESS)
@@ -737,8 +835,8 @@ inline int initudpcli(SOCKET* pSock, char* address, char* port)
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = inet_addr(address);
sa.sin_port = htons((unsigned short)atoi(port));
+ sa.sin_addr.s_addr = inet_addr(address);
// // Associate the client to the desired address and port.
// if (bind(*pSock, (struct sockaddr*)&sa, sizeof(sa)) != EXIT_SUCCESS)
@@ -876,13 +974,29 @@ inline int inittcpsrv(SOCKET* pSock, char* address, char* port, int maxnbcli, in
return EXIT_FAILURE;
}
+#ifndef DISABLE_TCPSERVER_SO_REUSEADDR
+ // Enable immediate reuse of the address and port.
+ if (setsocketreuseaddr(*pSock, TRUE) != EXIT_SUCCESS)
+ {
+ PRINT_DEBUG_ERROR_OSNET(("inittcpsrv error (%s) : %s(address=%s, port=%s, maxnbcli=%d, timeout=%d)\n",
+ strtime_m(),
+ "setsocketreuseaddr failed. ",
+ address, port, maxnbcli, timeout));
+ closesocket(*pSock);
+#ifdef _WIN32
+ WSACleanup();
+#endif // _WIN32
+ return EXIT_FAILURE;
+ }
+#endif // DISABLE_TCPSERVER_SO_REUSEADDR
+
memset(&sa, 0, sizeof(sa));
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server.
sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = inet_addr(address);
sa.sin_port = htons((unsigned short)atoi(port));
+ sa.sin_addr.s_addr = inet_addr(address);
// Associate the server to the desired address and port.
if (bind(*pSock, (struct sockaddr*)&sa, sizeof(sa)) != EXIT_SUCCESS)
@@ -1018,13 +1132,29 @@ inline int initudpsrv(SOCKET* pSock, char* address, char* port, int timeout)
return EXIT_FAILURE;
}
+#ifndef DISABLE_UDPSERVER_SO_REUSEADDR
+ // Enable immediate reuse of the address and port.
+ if (setsocketreuseaddr(*pSock, TRUE) != EXIT_SUCCESS)
+ {
+ PRINT_DEBUG_ERROR_OSNET(("initudpsrv error (%s) : %s(address=%s, port=%s, timeout=%d)\n",
+ strtime_m(),
+ "setsocketreuseaddr failed. ",
+ address, port, timeout));
+ closesocket(*pSock);
+#ifdef _WIN32
+ WSACleanup();
+#endif // _WIN32
+ return EXIT_FAILURE;
+ }
+#endif // DISABLE_UDPSERVER_SO_REUSEADDR
+
memset(&sa, 0, sizeof(sa));
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server.
sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = inet_addr(address);
sa.sin_port = htons((unsigned short)atoi(port));
+ sa.sin_addr.s_addr = inet_addr(address);
// Associate the server to the desired address and port.
if (bind(*pSock, (struct sockaddr*)&sa, sizeof(sa)) != EXIT_SUCCESS)
@@ -1040,6 +1170,20 @@ inline int initudpsrv(SOCKET* pSock, char* address, char* port, int timeout)
return EXIT_FAILURE;
}
+// // Set defaults for recv()... and send()...
+// if (connect(*pSock, (struct sockaddr*)&sa, sizeof(sa)) != EXIT_SUCCESS)
+// {
+// PRINT_DEBUG_ERROR_OSNET(("initudpsrv error (%s) : %s(address=%s, port=%s, timeout=%d)\n",
+// strtime_m(),
+// WSAGetLastErrorMsg(),
+// address, port, timeout));
+// closesocket(*pSock);
+//#ifdef _WIN32
+// WSACleanup();
+//#endif // _WIN32
+// return EXIT_FAILURE;
+// }
+
return EXIT_SUCCESS;
}
@@ -1153,6 +1297,8 @@ inline int waitforclifortcpsrv(SOCKET socksrv, SOCKET* pSockCli, int timeout)
return EXIT_TIMEOUT;
}
+ memset(&addr, 0, sizeof(addr));
+ addrlen = sizeof(addr);
*pSockCli = accept(socksrv, (struct sockaddr*)&addr, &addrlen);
if (*pSockCli == INVALID_SOCKET)
{
@@ -1171,6 +1317,7 @@ inline int waitforclifortcpsrv(SOCKET socksrv, SOCKET* pSockCli, int timeout)
strtime_m(),
"getnameinfo failed. ",
(int)socksrv, timeout));
+ closesocket(*pSockCli);
return EXIT_FAILURE;
}
@@ -1189,16 +1336,17 @@ int timeout : (IN) Max time to wait in ms (0 to disable timeout).
Return : EXIT_SUCCESS if there is a client, EXIT_TIMEOUT if there is no client
after the timeout elapses or EXIT_FAILURE if there is an error.
*/
+//inline int waitforcliforudpsrv(SOCKET socksrv, SOCKET* pSockCli, int timeout, char* firstdgram, int firstdgramlen)
inline int waitforcliforudpsrv(SOCKET socksrv, SOCKET* pSockCli, int timeout)
{
fd_set sock_set;
int iResult = SOCKET_ERROR;
struct timeval tv;
- // struct sockaddr_storage addr;
- // socklen_t addrlen = sizeof(struct sockaddr_storage);
- // char hostname[NI_MAXHOST];
- // char service[NI_MAXSERV];
- // char buf[1];
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(struct sockaddr_storage);
+ char hostname[NI_MAXHOST];
+ char service[NI_MAXSERV];
+ char buf[65535];
tv.tv_sec = (long)(timeout/1000);
tv.tv_usec = (long)((timeout%1000)*1000);
@@ -1242,32 +1390,67 @@ inline int waitforcliforudpsrv(SOCKET socksrv, SOCKET* pSockCli, int timeout)
return EXIT_TIMEOUT;
}
- //recvfrom(socksrv, buf, 0, 0, (struct sockaddr*)&addr, (socklen_t*)&addrlen);
+ // First datagram will be lost...
+ memset(&addr, 0, sizeof(addr));
+ addrlen = sizeof(addr);
+ if (recvfrom(socksrv, buf, sizeof(buf), 0, (struct sockaddr*)&addr, (socklen_t*)&addrlen) < 0)
+ {
+ PRINT_DEBUG_ERROR_OSNET(("waitforcliforudpsrv error (%s) : %s(socksrv=%d, timeout=%d)\n",
+ strtime_m(),
+ WSAGetLastErrorMsg(),
+ (int)socksrv, timeout));
+ return EXIT_FAILURE;
+ }
+
+ // Should create a new socket connected to that client...?
- //// Connect to client.
- //if (connect(socksrv, (struct sockaddr*)&addr, addrlen) != EXIT_SUCCESS)
+ //// Create a UDP IPv4 socket.
+ //*pSockCli = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ //if (*pSockCli == INVALID_SOCKET)
//{
// PRINT_DEBUG_ERROR_OSNET(("waitforcliforudpsrv error (%s) : %s(socksrv=%d, timeout=%d)\n",
// strtime_m(),
- // "connect failed. ",
+ // WSAGetLastErrorMsg(),
// (int)socksrv, timeout));
// return EXIT_FAILURE;
//}
- //// Display hostname and service.
- //if (getnameinfo((struct sockaddr*)&addr, addrlen, hostname, NI_MAXHOST, service,
- // NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV) != EXIT_SUCCESS)
+ //// Configure timeouts for send and recv.
+ //if (setsockettimeouts(*pSockCli, DEFAULT_SOCK_TIMEOUT) != EXIT_SUCCESS)
//{
// PRINT_DEBUG_ERROR_OSNET(("waitforcliforudpsrv error (%s) : %s(socksrv=%d, timeout=%d)\n",
// strtime_m(),
- // "getnameinfo failed. ",
+ // WSAGetLastErrorMsg(),
// (int)socksrv, timeout));
+ // closesocket(*pSockCli);
// return EXIT_FAILURE;
//}
+
+ // Set defaults for recv()... and send()...
+ //if (connect(*pSockCli, (struct sockaddr*)&addr, addrlen) != EXIT_SUCCESS)
+ if (connect(socksrv, (struct sockaddr*)&addr, addrlen) != EXIT_SUCCESS)
+ {
+ PRINT_DEBUG_ERROR_OSNET(("waitforcliforudpsrv error (%s) : %s(socksrv=%d, timeout=%d)\n",
+ strtime_m(),
+ WSAGetLastErrorMsg(),
+ (int)socksrv, timeout));
+ //closesocket(*pSockCli);
+ return EXIT_FAILURE;
+ }
- //PRINT_DEBUG_MESSAGE_OSNET(("Accepted connection from host %s and port %s\n", hostname, service));
+ // Display hostname and service.
+ if (getnameinfo((struct sockaddr*)&addr, addrlen, hostname, NI_MAXHOST, service,
+ NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV) != EXIT_SUCCESS)
+ {
+ PRINT_DEBUG_ERROR_OSNET(("waitforcliforudpsrv error (%s) : %s(socksrv=%d, timeout=%d)\n",
+ strtime_m(),
+ "getnameinfo failed. ",
+ (int)socksrv, timeout));
+ //closesocket(*pSockCli);
+ return EXIT_FAILURE;
+ }
- PRINT_DEBUG_MESSAGE_OSNET(("Accepted connection\n"));
+ PRINT_DEBUG_MESSAGE_OSNET(("Accepted connection from host %s and port %s\n", hostname, service));
*pSockCli = socksrv;
@@ -1319,25 +1502,30 @@ Return : EXIT_SUCCESS or EXIT_FAILURE if there is an error.
*/
inline int disconnectclifromudpsrv(SOCKET sock)
{
- // Shutdown the connection.
- if (shutdown(sock, SD_BOTH) != EXIT_SUCCESS)
- {
- PRINT_DEBUG_WARNING_OSNET(("disconnectclifromudpsrv warning (%s) : %s(sock=%d)\n",
- strtime_m(),
- "shutdown failed. ",
- (int)sock));
- //return EXIT_FAILURE;
- }
- // Destroy the socket created by socket().
- if (closesocket(sock) != EXIT_SUCCESS)
- {
- PRINT_DEBUG_ERROR_OSNET(("disconnectclifromudpsrv error (%s) : %s(sock=%d)\n",
- strtime_m(),
- "closesocket failed. ",
- (int)sock));
- return EXIT_FAILURE;
- }
+ // Should create another socket correctly bound in waitforcliudpsrv()...?
+
+ UNREFERENCED_PARAMETER(sock);
+
+ //// Shutdown the connection.
+ //if (shutdown(sock, SD_BOTH) != EXIT_SUCCESS)
+ //{
+ // PRINT_DEBUG_WARNING_OSNET(("disconnectclifromudpsrv warning (%s) : %s(sock=%d)\n",
+ // strtime_m(),
+ // "shutdown failed. ",
+ // (int)sock));
+ // //return EXIT_FAILURE;
+ //}
+
+ //// Destroy the socket created by socket().
+ //if (closesocket(sock) != EXIT_SUCCESS)
+ //{
+ // PRINT_DEBUG_ERROR_OSNET(("disconnectclifromudpsrv error (%s) : %s(sock=%d)\n",
+ // strtime_m(),
+ // "closesocket failed. ",
+ // (int)sock));
+ // return EXIT_FAILURE;
+ //}
return EXIT_SUCCESS;
}
@@ -1522,26 +1710,58 @@ inline int LaunchMultiCliTCPSrv(char* port, int (*handlecli)(SOCKET, void*), voi
return EXIT_SUCCESS;
}
-#endif // DISABLE_THREADS_OSNET
+#endif // !DISABLE_THREADS_OSNET
#ifdef _MSC_VER
// Restore the Visual Studio warnings previously disabled.
#pragma warning(default : 4702)
//#pragma warning(default : 4127)
#endif // _MSC_VER
-// The 2 following functions are a little bit deprecated...
+#ifndef DISABLE_IOCTLSOCKET
+/*
+Check for any data available to read on a socket.
+
+SOCKET sock : (IN) Socket.
+
+Return : EXIT_SUCCESS if there is data to read from the socket, EXIT_TIMEOUT if a timeout occurs or
+EXIT_FAILURE if there is an error.
+*/
+inline int checkavailablebytessocket(SOCKET sock)
+{
+//#ifdef _WIN32
+ unsigned long bytes_avail = 0;
+//#else
+// int bytes_avail = 0;
+//#endif // _WIN32
+
+ if (ioctlsocket(sock, FIONREAD, &bytes_avail) != EXIT_SUCCESS)
+ {
+ PRINT_DEBUG_ERROR_OSNET(("checkavailablebytessocket error (%s) : (FIONREAD) %s(sock=%d)\n",
+ strtime_m(),
+ WSAGetLastErrorMsg(),
+ (int)sock));
+ return EXIT_FAILURE;
+ }
+ if (bytes_avail <= 0) return EXIT_TIMEOUT;
+
+ return EXIT_SUCCESS;
+}
+#endif // !DISABLE_IOCTLSOCKET
+
+// The 2 following functions should be used with caution...
#ifdef _MSC_VER
// Disable some Visual Studio warnings.
#pragma warning(disable : 4127)
#endif // _MSC_VER
/*
-Wait for data to read on a given socket.
+Wait for data to read on a socket.
SOCKET sock : (IN) Socket.
-timeval timeout : (IN) max time to wait before returning.
+timeval timeout : (IN) Max time to wait before returning.
-Return : EXIT_SUCCESS or EXIT_FAILURE if there is an error or no data to read from the socket after the timeout.
+Return : EXIT_SUCCESS if there is data to read from the socket, EXIT_TIMEOUT if a timeout occurs or
+EXIT_FAILURE if there is an error.
*/
inline int waitforsocket(SOCKET sock, struct timeval timeout)
{
@@ -1577,7 +1797,7 @@ inline int waitforsocket(SOCKET sock, struct timeval timeout)
}
/*
-Eliminate all the data coming from a given socket (if any).
+Eliminate all the data coming from a socket (if any).
SOCKET sock : (IN) Socket.
@@ -1636,7 +1856,7 @@ inline int flushsocket(SOCKET sock)
#endif // _MSC_VER
/*
-Send data to a given socket. Retry automatically if all the bytes were not sent.
+Send data to a socket. Retry automatically if all the bytes were not sent.
Fail when a timeout occurs if it is enabled on the socket.
SOCKET sock : (IN) Socket.
@@ -1683,7 +1903,7 @@ inline int sendall(SOCKET sock, char* sendbuf, int sendbuflen)
{
PRINT_DEBUG_ERROR_OSNET(("sendall error (%s) : %s(sock=%d, sendbuf=%#x, sendbuflen=%d)\n",
strtime_m(),
- "send failed. ",
+ WSAGetLastErrorMsg(),
(int)sock, sendbuf, sendbuflen));
#ifdef _DEBUG_MESSAGES_OSNET
for (i = 0; i < BytesSent; i++)
@@ -1712,7 +1932,7 @@ inline int sendall(SOCKET sock, char* sendbuf, int sendbuflen)
}
/*
-Receive data at a given socket. Retry automatically if all the bytes were not received.
+Receive data at a socket. Retry automatically if all the bytes were not received.
Fail when a timeout occurs if it is enabled on the socket.
SOCKET sock : (IN) Socket.
@@ -1759,7 +1979,7 @@ inline int recvall(SOCKET sock, char* recvbuf, int recvbuflen)
{
PRINT_DEBUG_ERROR_OSNET(("recvall error (%s) : %s(sock=%d, recvbuf=%#x, recvbuflen=%d)\n",
strtime_m(),
- "recv failed. ",
+ WSAGetLastErrorMsg(),
(int)sock, recvbuf, recvbuflen));
#ifdef _DEBUG_MESSAGES_OSNET
for (i = 0; i < BytesReceived; i++)
@@ -1825,7 +2045,7 @@ inline int sendtoall(SOCKET sock, char* sendbuf, int sendbuflen, struct sockaddr
{
PRINT_DEBUG_ERROR_OSNET(("sendtoall error (%s) : %s(sock=%d, sendbuf=%#x, sendbuflen=%d, sa=%#x, salen=%d)\n",
strtime_m(),
- "sendto failed. ",
+ WSAGetLastErrorMsg(),
(int)sock, sendbuf, sendbuflen, sa, salen));
#ifdef _DEBUG_MESSAGES_OSNET
for (i = 0; i < BytesSent; i++)
@@ -1891,7 +2111,7 @@ inline int recvfromall(SOCKET sock, char* recvbuf, int recvbuflen, struct sockad
{
PRINT_DEBUG_ERROR_OSNET(("recvfromall error (%s) : %s(sock=%d, recvbuf=%#x, recvbuflen=%d)\n",
strtime_m(),
- "recvfrom failed. ",
+ WSAGetLastErrorMsg(),
(int)sock, recvbuf, recvbuflen));
#ifdef _DEBUG_MESSAGES_OSNET
for (i = 0; i < BytesReceived; i++)
@@ -1957,7 +2177,7 @@ inline int recvlatest(SOCKET sock, char* recvbuf, int recvbuflen)
{
PRINT_DEBUG_ERROR_OSNET(("recvlatest error (%s) : %s(sock=%d, recvbuf=%#x, recvbuflen=%d)\n",
strtime_m(),
- "recv failed. ",
+ WSAGetLastErrorMsg(),
(int)sock, recvbuf, recvbuflen));
free(savebuf);
return EXIT_FAILURE;
@@ -1989,7 +2209,7 @@ inline int recvlatest(SOCKET sock, char* recvbuf, int recvbuflen)
{
PRINT_DEBUG_ERROR_OSNET(("recvlatest error (%s) : %s(sock=%d, recvbuf=%#x, recvbuflen=%d)\n",
strtime_m(),
- "recv failed. ",
+ WSAGetLastErrorMsg(),
(int)sock, recvbuf, recvbuflen));
free(savebuf);
return EXIT_FAILURE;
@@ -2019,7 +2239,7 @@ inline int recvlatest(SOCKET sock, char* recvbuf, int recvbuflen)
}
/*
-Receive data at a given socket until a specific end string is received.
+Receive data at a socket until a specific end string is received.
If this string is found (and the maximum number of bytes to receive has not
been reached), it is not necessarily the last received bytes in the buffer
(other bytes might have been received after).
@@ -2048,7 +2268,7 @@ inline int recvatleastuntilstr(SOCKET sock, char* recvbuf, char* endstr, int max
"recvbuf full. ",
(int)sock, recvbuf, endstr, maxrecvbuflen));
PRINT_DEBUG_MESSAGE_OSNET(("Total bytes received : %d\n", BytesReceived));
- return EXIT_FAILURE;
+ return EXIT_OUT_OF_MEMORY;
}
Bytes = recv(sock, recvbuf + BytesReceived, maxrecvbuflen - BytesReceived, 0);
@@ -2078,7 +2298,7 @@ inline int recvatleastuntilstr(SOCKET sock, char* recvbuf, char* endstr, int max
{
PRINT_DEBUG_ERROR_OSNET(("recvatleastuntil error (%s) : %s(sock=%d, recvbuf=%#x, endstr=%s, maxrecvbuflen=%d)\n",
strtime_m(),
- "recv failed. ",
+ WSAGetLastErrorMsg(),
(int)sock, recvbuf, endstr, maxrecvbuflen));
PRINT_DEBUG_MESSAGE_OSNET(("Total bytes received : %d\n", BytesReceived));
return EXIT_FAILURE;
@@ -2093,7 +2313,7 @@ inline int recvatleastuntilstr(SOCKET sock, char* recvbuf, char* endstr, int max
}
/*
-Receive data at a given socket until a specific end character is received.
+Receive data at a socket until a specific end character is received.
If this character is found (and the maximum number of bytes to receive has not
been reached), it is not necessarily the last received byte in the buffer
(other bytes might have been received after).
@@ -2121,7 +2341,7 @@ inline int recvatleastuntil(SOCKET sock, char* recvbuf, char endchar, int maxrec
"recvbuf full. ",
(int)sock, recvbuf, (int)(unsigned char)endchar, maxrecvbuflen));
PRINT_DEBUG_MESSAGE_OSNET(("Total bytes received : %d\n", BytesReceived));
- return EXIT_FAILURE;
+ return EXIT_OUT_OF_MEMORY;
}
Bytes = recv(sock, recvbuf + BytesReceived, maxrecvbuflen - BytesReceived, 0);
@@ -2162,7 +2382,7 @@ inline int recvatleastuntil(SOCKET sock, char* recvbuf, char endchar, int maxrec
{
PRINT_DEBUG_ERROR_OSNET(("recvatleastuntil error (%s) : %s(sock=%d, recvbuf=%#x, endchar=%.2x, maxrecvbuflen=%d)\n",
strtime_m(),
- "recv failed. ",
+ WSAGetLastErrorMsg(),
(int)sock, recvbuf, (int)(unsigned char)endchar, maxrecvbuflen));
PRINT_DEBUG_MESSAGE_OSNET(("Total bytes received : %d\n", BytesReceived));
return EXIT_FAILURE;
@@ -2177,7 +2397,7 @@ inline int recvatleastuntil(SOCKET sock, char* recvbuf, char endchar, int maxrec
}
/*
-Receive data at a given socket until a specific end character is received.
+Receive data at a socket until a specific end character is received.
If this character is found (and the maximum number of bytes to receive has not
been reached), it is the last received byte in the buffer.
This function might take more network load than recvatleastuntil() but guarantees
@@ -2207,7 +2427,7 @@ inline int recvuntil(SOCKET sock, char* recvbuf, char endchar, int maxrecvbuflen
"recvbuf full. ",
(int)sock, recvbuf, (int)(unsigned char)endchar, maxrecvbuflen));
PRINT_DEBUG_MESSAGE_OSNET(("Total bytes received : %d\n", BytesReceived));
- return EXIT_FAILURE;
+ return EXIT_OUT_OF_MEMORY;
}
// Receive 1 byte.
@@ -2232,7 +2452,7 @@ inline int recvuntil(SOCKET sock, char* recvbuf, char endchar, int maxrecvbuflen
{
PRINT_DEBUG_ERROR_OSNET(("recvuntil error (%s) : %s(sock=%d, recvbuf=%#x, endchar=%.2x, maxrecvbuflen=%d)\n",
strtime_m(),
- "recv failed. ",
+ WSAGetLastErrorMsg(),
(int)sock, recvbuf, (int)(unsigned char)endchar, maxrecvbuflen));
PRINT_DEBUG_MESSAGE_OSNET(("Total bytes received : %d\n", BytesReceived));
return EXIT_FAILURE;
@@ -2263,7 +2483,8 @@ inline int recvuntilstr(SOCKET sock, char* recvbuf, char* endstr, int maxrecvbuf
"recvbuf full. ",
(int)sock, recvbuf, endstr, maxrecvbuflen));
PRINT_DEBUG_MESSAGE_OSNET(("Total bytes received : %d\n", BytesReceived));
- return EXIT_FAILURE;
+ *pBytesReceived = BytesReceived;
+ return EXIT_OUT_OF_MEMORY;
}
// Receive 1 byte.
@@ -2277,6 +2498,7 @@ inline int recvuntilstr(SOCKET sock, char* recvbuf, char* endstr, int maxrecvbuf
szOSUtilsErrMsgs[EXIT_TIMEOUT],
(int)sock, recvbuf, endstr, maxrecvbuflen));
PRINT_DEBUG_MESSAGE_OSNET(("Total bytes received : %d\n", BytesReceived));
+ *pBytesReceived = BytesReceived;
return EXIT_TIMEOUT;
}
else
@@ -2288,9 +2510,10 @@ inline int recvuntilstr(SOCKET sock, char* recvbuf, char* endstr, int maxrecvbuf
{
PRINT_DEBUG_ERROR_OSNET(("recvuntilstr error (%s) : %s(sock=%d, recvbuf=%#x, endstr=%s, maxrecvbuflen=%d)\n",
strtime_m(),
- "recv failed. ",
+ WSAGetLastErrorMsg(),
(int)sock, recvbuf, endstr, maxrecvbuflen));
PRINT_DEBUG_MESSAGE_OSNET(("Total bytes received : %d\n", BytesReceived));
+ *pBytesReceived = BytesReceived;
return EXIT_FAILURE;
}
@@ -2304,4 +2527,175 @@ inline int recvuntilstr(SOCKET sock, char* recvbuf, char* endstr, int maxrecvbuf
return EXIT_SUCCESS;
}
-#endif // OSNET_H
+/*
+Get address, port and type from a path.
+
+char* szDevPath : (IN) Server TCP port (e.g. :4001), client IP address and TCP port (e.g. 127.0.0.1:4001),
+server UDP port (udp:4001), client IP address and UDP port (e.g. udp://127.0.0.1:4001) or an other path.
+char* address : (OUT) IPv4 address found.
+size_t addresslen : (IN) Number of bytes of the address buffer.
+char* port : (OUT) TCP or UDP port found.
+size_t portlen : (IN) Number of bytes of the port buffer.
+int* pDevType: (OUT) OTHER_DEV_TYPE_OSNET, TCP_CLIENT_DEV_TYPE_OSNET, TCP_SERVER_DEV_TYPE_OSNET, UDP_CLIENT_DEV_TYPE_OSNET or UDP_SERVER_DEV_TYPE_OSNET.
+
+Return : EXIT_SUCCESS or EXIT_FAILURE if there is an error.
+*/
+inline int GetAddrPortTypeFromDevPath(char* szDevPath, char* address, size_t addresslen, char* port, size_t portlen, int* pDevType)
+{
+ char* ptr = NULL;
+ char* ptr2 = NULL;
+ size_t tmplen = 0;
+
+ if ((szDevPath == NULL)||(address == NULL)||(port == NULL)||(pDevType == NULL)||(addresslen < 16)||(portlen < 6)) return EXIT_FAILURE;
+
+ address[0] = 0;
+ port[0] = 0;
+ *pDevType = OTHER_DEV_TYPE_OSNET;
+
+ ptr = strchr(szDevPath, ':');
+ if ((ptr != NULL)&&(strlen(ptr) >= 6)) ptr2 = strchr(ptr+1, ':');
+
+ if ((strlen(szDevPath) >= 12+7+1+1)&&(strncmp(szDevPath, "tcp-connect:", strlen("tcp-connect:")) == 0)&&(ptr2 != NULL)&&(ptr2[1] != 0))
+ {
+ tmplen = ptr2-(szDevPath+12);
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr2+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath+12, tmplen);
+ address[tmplen+1] = 0;
+ strcpy(port, ptr2+1);
+ *pDevType = TCP_CLIENT_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 11+7+1+1)&&(strncmp(szDevPath, "tcp-listen:", strlen("tcp-listen:")) == 0)&&(ptr2 != NULL)&&(ptr2[1] != 0))
+ {
+ tmplen = ptr2-(szDevPath+11);
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr2+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath+11, tmplen);
+ address[tmplen+1] = 0;
+ strcpy(port, ptr2+1);
+ *pDevType = TCP_SERVER_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 11+7+1+1)&&(strncmp(szDevPath, "udp-listen:", strlen("udp-listen:")) == 0)&&(ptr2 != NULL)&&(ptr2[1] != 0))
+ {
+ tmplen = ptr2-(szDevPath+11);
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr2+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath+11, tmplen);
+ address[tmplen+1] = 0;
+ strcpy(port, ptr2+1);
+ *pDevType = UDP_SERVER_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 9+7+1+1)&&((strncmp(szDevPath, "tcpsrv://", strlen("tcpsrv://")) == 0)||(strncmp(szDevPath, "tcpsvr://", strlen("tcpsvr://")) == 0))&&(ptr2 != NULL)&&(ptr2[1] != 0))
+ {
+ tmplen = ptr2-(szDevPath+9);
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr2+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath+9, tmplen);
+ address[tmplen+1] = 0;
+ strcpy(port, ptr2+1);
+ *pDevType = TCP_SERVER_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 9+7+1+1)&&((strncmp(szDevPath, "udpsrv://", strlen("udpsrv://")) == 0)||(strncmp(szDevPath, "udpsvr://", strlen("udpsvr://")) == 0))&&(ptr2 != NULL)&&(ptr2[1] != 0))
+ {
+ tmplen = ptr2-(szDevPath+9);
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr2+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath+9, tmplen);
+ address[tmplen+1] = 0;
+ strcpy(port, ptr2+1);
+ *pDevType = UDP_SERVER_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 7+7+1+1)&&((strncmp(szDevPath, "tcpsrv:", strlen("tcpsrv:")) == 0)||(strncmp(szDevPath, "tcpsvr:", strlen("tcpsvr:")) == 0))&&(ptr2 != NULL)&&(ptr2[1] != 0))
+ {
+ tmplen = ptr2-(szDevPath+7);
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr2+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath+7, tmplen);
+ address[tmplen+1] = 0;
+ strcpy(port, ptr2+1);
+ *pDevType = TCP_SERVER_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 7+7+1+1)&&((strncmp(szDevPath, "udpsrv:", strlen("udpsrv:")) == 0)||(strncmp(szDevPath, "udpsvr:", strlen("udpsvr:")) == 0))&&(ptr2 != NULL)&&(ptr2[1] != 0))
+ {
+ tmplen = ptr2-(szDevPath+7);
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr2+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath+7, tmplen);
+ address[tmplen+1] = 0;
+ strcpy(port, ptr2+1);
+ *pDevType = UDP_SERVER_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 6+7+1+1)&&(strncmp(szDevPath, "tcp://", strlen("tcp://")) == 0)&&(ptr2 != NULL)&&(ptr2[1] != 0))
+ {
+ tmplen = ptr2-(szDevPath+6);
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr2+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath+6, tmplen);
+ address[tmplen+1] = 0;
+ strcpy(port, ptr2+1);
+ *pDevType = TCP_CLIENT_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 6+7+1+1)&&(strncmp(szDevPath, "udp://", strlen("udp://")) == 0)&&(ptr2 != NULL)&&(ptr2[1] != 0))
+ {
+ tmplen = ptr2-(szDevPath+6);
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr2+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath+6, tmplen);
+ address[tmplen+1] = 0;
+ strcpy(port, ptr2+1);
+ *pDevType = UDP_CLIENT_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 4+7+1+1)&&(strncmp(szDevPath, "tcp:", strlen("tcp:")) == 0)&&(ptr2 != NULL)&&(ptr2[1] != 0))
+ {
+ tmplen = ptr2-(szDevPath+4);
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr2+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath+4, tmplen);
+ address[tmplen+1] = 0;
+ strcpy(port, ptr2+1);
+ *pDevType = TCP_CLIENT_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 4+7+1+1)&&(strncmp(szDevPath, "udp:", strlen("udp:")) == 0)&&(ptr2 != NULL)&&(ptr2[1] != 0))
+ {
+ tmplen = ptr2-(szDevPath+4);
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr2+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath+4, tmplen);
+ address[tmplen+1] = 0;
+ strcpy(port, ptr2+1);
+ *pDevType = UDP_CLIENT_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 7+1)&&((strncmp(szDevPath, "tcpsrv:", strlen("tcpsrv:")) == 0)||(strncmp(szDevPath, "tcpsvr:", strlen("tcpsvr:")) == 0))&&(atoi(szDevPath+4) > 0))
+ {
+ if (portlen < strlen(szDevPath+7)+1) return EXIT_FAILURE;
+ strcpy(port, szDevPath+7);
+ *pDevType = TCP_SERVER_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 7+1)&&((strncmp(szDevPath, "udpsrv:", strlen("udpsrv:")) == 0)||(strncmp(szDevPath, "udpsvr:", strlen("udpsvr:")) == 0))&&(atoi(szDevPath+4) > 0))
+ {
+ if (portlen < strlen(szDevPath+7)+1) return EXIT_FAILURE;
+ strcpy(port, szDevPath+7);
+ *pDevType = UDP_SERVER_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 4+1)&&(strncmp(szDevPath, "tcp:", strlen("tcp:")) == 0)&&(atoi(szDevPath+4) > 0))
+ {
+ if (portlen < strlen(szDevPath+4)+1) return EXIT_FAILURE;
+ strcpy(port, szDevPath+4);
+ *pDevType = TCP_SERVER_DEV_TYPE_OSNET;
+ }
+ else if ((strlen(szDevPath) >= 4+1)&&(strncmp(szDevPath, "udp:", strlen("udp:")) == 0)&&(atoi(szDevPath+4) > 0))
+ {
+ if (portlen < strlen(szDevPath+4)+1) return EXIT_FAILURE;
+ strcpy(port, szDevPath+4);
+ *pDevType = UDP_SERVER_DEV_TYPE_OSNET;
+ }
+ else if ((ptr != NULL)&&(szDevPath[0] == ':')&&(atoi(szDevPath+1) > 0))
+ {
+ if (portlen < strlen(szDevPath+1)+1) return EXIT_FAILURE;
+ strcpy(port, szDevPath+1);
+ *pDevType = TCP_SERVER_DEV_TYPE_OSNET;
+ }
+ else if ((ptr != NULL)&&(atoi(ptr+1) > 0)&&(isdigit((unsigned char)szDevPath[0])))
+ {
+ tmplen = ptr-szDevPath;
+ if ((addresslen < tmplen+1)||(portlen < strlen(ptr+1)+1)) return EXIT_FAILURE;
+ memcpy(address, szDevPath, tmplen);
+ address[tmplen+1] = 0;
+ //strcpy(port, ptr+1);
+ sprintf(port, "%d", atoi(ptr+1)); // Other non-digit characters may follow the port...
+ *pDevType = TCP_CLIENT_DEV_TYPE_OSNET;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+#endif // !OSNET_H
diff --git a/CamSvcSrv/jni/OSThread.c b/CamSvcSrv/jni/OSThread.c
index 39f2d97..1f38e03 100644
--- a/CamSvcSrv/jni/OSThread.c
+++ b/CamSvcSrv/jni/OSThread.c
@@ -31,7 +31,7 @@ Created : 2007
//int THREAD_PRIORITY_BELOW_NORMAL = 40;
//int THREAD_PRIORITY_LOWEST = 1;
//int THREAD_PRIORITY_IDLE = 0;
-#endif // _WIN32
+#endif // !_WIN32
#ifdef ENABLE_CANCEL_THREAD
#ifdef _WIN32
diff --git a/CamSvcSrv/jni/OSThread.h b/CamSvcSrv/jni/OSThread.h
index 9a2f090..f0a7806 100644
--- a/CamSvcSrv/jni/OSThread.h
+++ b/CamSvcSrv/jni/OSThread.h
@@ -62,12 +62,12 @@ Debug macros specific to OSThread.
#ifndef USE_CREATE_THREAD
#define USE_CREATE_THREAD
#endif // USE_CREATE_THREAD
-#endif // WINCE
+#endif // !WINCE
#ifdef _WIN32
#ifndef USE_CREATE_THREAD
#include
-#endif // USE_CREATE_THREAD
+#endif // !USE_CREATE_THREAD
#else
#include
//#include
@@ -86,13 +86,13 @@ typedef DWORD THREAD_IDENTIFIER;
#define THREAD_PROC_RETURN_VALUE DWORD WINAPI
typedef LPTHREAD_START_ROUTINE PTHREAD_PROC;
#else
-#if defined(__cplusplus) && defined(_M_CEE)
-#define THREAD_PROC_RETURN_VALUE unsigned __clrcall
-typedef unsigned (__clrcall *PTHREAD_PROC)(void*);
-#else
+//#if defined(__cplusplus) && defined(_M_CEE)
+//#define THREAD_PROC_RETURN_VALUE unsigned __clrcall
+//typedef unsigned (__clrcall *PTHREAD_PROC)(void*);
+//#else
#define THREAD_PROC_RETURN_VALUE unsigned __stdcall
typedef unsigned (__stdcall *PTHREAD_PROC)(void*);
-#endif // defined(__cplusplus) && defined(_M_CEE)
+//#endif // defined(__cplusplus) && defined(_M_CEE)
#endif // USE_CREATE_THREAD
#else
typedef pthread_t THREAD_IDENTIFIER;
@@ -245,7 +245,7 @@ inline int CreateDefaultThread(PTHREAD_PROC pThreadProc, void* pParam, THREAD_ID
pthread_attr_destroy(&attr);
return EXIT_FAILURE;
}
-#endif // __ANDROID__
+#endif // !__ANDROID__
// Only PTHREAD_SCOPE_SYSTEM is supported on Linux. This is the default on Linux.
// That is a pity as PTHREAD_SCOPE_PROCESS seems to describe a behaviour similar
@@ -333,7 +333,7 @@ inline int CreateDefaultThread(PTHREAD_PROC pThreadProc, void* pParam, THREAD_ID
pthread_detach(*pThreadId);
#ifndef __ANDROID__
pthread_cancel(*pThreadId);
-#endif // __ANDROID__
+#endif // !__ANDROID__
return EXIT_FAILURE;
}
#endif // _WIN32
@@ -450,7 +450,7 @@ inline int WaitForThread(THREAD_IDENTIFIER ThreadId)
GetLastErrorMsg(),
ThreadId));
}
-#endif // WINCE
+#endif // !WINCE
#else
// Wait until the thread has terminated.
// Note : pthread_join() may fail if the thread identifier is bad. This can be because
@@ -568,7 +568,7 @@ inline int WaitForThreadWithTimeout(THREAD_IDENTIFIER ThreadId, int timeout)
ThreadId, timeout));
break;
}
-#endif // WINCE
+#endif // !WINCE
#else
int iResult = EXIT_FAILURE;
struct timespec abstime;
@@ -726,7 +726,7 @@ inline int KillThread(THREAD_IDENTIFIER ThreadId)
GetLastErrorMsg(),
ThreadId));
}
-#endif // WINCE
+#endif // !WINCE
#else
int iResult = pthread_detach(ThreadId);
switch (iResult)
@@ -870,7 +870,7 @@ inline int CancelThread(THREAD_IDENTIFIER ThreadId)
GetLastErrorMsg(),
ThreadId));
}
-#endif // WINCE
+#endif // !WINCE
#else
int iResult = pthread_detach(ThreadId);
switch (iResult)
@@ -996,7 +996,7 @@ inline void ThreadYield(void)
SwitchToThread();
#else
Sleep(0);
-#endif // WINCE
+#endif // !WINCE
#else
// Disabled by default because it is a GNU extension.
#ifdef ENABLE_PTHREAD_YIELD
@@ -1072,7 +1072,7 @@ inline int SetThreadDefaultPriority(THREAD_IDENTIFIER ThreadId, int Priority)
ThreadId, Priority));
return EXIT_FAILURE;
}
-#endif // WINCE
+#endif // !WINCE
#else
struct sched_param param;
int policy = 0;
@@ -1178,7 +1178,7 @@ inline int GetThreadDefaultPriority(THREAD_IDENTIFIER ThreadId, int* pPriority)
ThreadId));
return EXIT_FAILURE;
}
-#endif // WINCE
+#endif // !WINCE
#else
struct sched_param param;
int policy = 0;
@@ -1263,7 +1263,7 @@ inline int SetThreadDefaultProcessor(THREAD_IDENTIFIER ThreadId, int ProcessorNu
ThreadId, ProcessorNumber));
return EXIT_FAILURE;
}
-#endif // WINCE
+#endif // !WINCE
#else
cpu_set_t cpuset;
@@ -1285,4 +1285,4 @@ inline int SetThreadDefaultProcessor(THREAD_IDENTIFIER ThreadId, int ProcessorNu
}
#endif // ENABLE_SET_THREAD_DEFAULT_PROCESSOR
-#endif // OSTHREAD_H
+#endif // !OSTHREAD_H
diff --git a/CamSvcSrv/jni/OSTime.c b/CamSvcSrv/jni/OSTime.c
index f4dd0bd..4fcdaa5 100644
--- a/CamSvcSrv/jni/OSTime.c
+++ b/CamSvcSrv/jni/OSTime.c
@@ -24,7 +24,9 @@ Created : 2009-01-28
#include "OSTime.h"
char strftime_m_tmpbuf[64]; // Used to store the string returned by strtime_m().
+char strftimeex_m_tmpbuf[64]; // Used to store the string returned by strtimeex_m().
char strftime_fns_tmpbuf[64]; // Used to store the string returned by strtime_fns().
+char strftimeex_fns_tmpbuf[64]; // Used to store the string returned by strtimeex_fns().
/*
Return a string like ctime() but in this format :
@@ -112,11 +114,119 @@ char* strtime_m(void)
#endif // UNICODE
strftime_m_tmpbuf[sizeof(strftime_m_tmpbuf)-1] = 0;
free(tstr); tstr = NULL;
-#endif // WINCE
+#endif // !WINCE
return strftime_m_tmpbuf;
}
+#if (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
+/*
+Return a string like ctime() but in this format :
+
+2007-08-27 19:28:04:00\0
+
+(without the "\n" of ctime()).
+Should not be used in concurrent threads as the string value returned might
+be changed by another thread.
+
+Return : This string.
+*/
+char* strtimeex_m(void)
+{
+ char sztmp[4];
+ struct timeval tv;
+#ifndef WINCE
+ time_t tt;
+ struct tm *timeptr = NULL;
+
+ memset(strftimeex_m_tmpbuf, 0, sizeof(strftimeex_m_tmpbuf));
+
+ if (gettimeofday(&tv, NULL) != EXIT_SUCCESS) { tv.tv_sec = 0; tv.tv_usec = 0; time(&tt); }
+ else { tt = tv.tv_sec; }
+ timeptr = localtime(&tt);
+
+ if (timeptr == NULL)
+ {
+ return strftimeex_m_tmpbuf;
+ }
+
+ // Use strftime to build a customized time string.
+ if (strftime(
+ strftimeex_m_tmpbuf,
+ sizeof(strftimeex_m_tmpbuf),
+ "%Y-%m-%d %H:%M:%S",
+ timeptr
+ ) <= 0)
+ {
+ memset(strftimeex_m_tmpbuf, 0, sizeof(strftimeex_m_tmpbuf));
+ return strftimeex_m_tmpbuf;
+ }
+#else
+ int nb = 0;
+ TCHAR* tstr = (TCHAR*)calloc(sizeof(strftimeex_m_tmpbuf), sizeof(TCHAR));
+
+ memset(strftimeex_m_tmpbuf, 0, sizeof(strftimeex_m_tmpbuf));
+
+ if (tstr == NULL)
+ {
+ return strftimeex_m_tmpbuf;
+ }
+
+ memset(tstr, 0, sizeof(strftimeex_m_tmpbuf)*sizeof(TCHAR));
+
+ // Use GetDateFormat() and GetTimeFormat() to build a customized time string.
+ nb = GetDateFormat(
+ MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), // Locale.
+ 0, // Flags.
+ NULL, // Current local system date.
+ _T("yyyy'-'MM'-'dd' '"), // Format the string.
+ tstr,
+ sizeof(strftimeex_m_tmpbuf)
+ );
+ if (nb <= 0)
+ {
+ free(tstr); tstr = NULL;
+ return strftimeex_m_tmpbuf;
+ }
+
+ if (GetTimeFormat(
+ MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), // Locale.
+ 0, // Flags.
+ NULL, // Current local system time.
+ _T("HH':'mm':'ss"), // Format the string.
+ tstr+(nb-1),
+ sizeof(strftimeex_m_tmpbuf)-(nb-1)
+ ) <= 0)
+ {
+ free(tstr); tstr = NULL;
+ return strftimeex_m_tmpbuf;
+ }
+
+ if (gettimeofday(&tv, NULL) != EXIT_SUCCESS) { tv.tv_sec = 0; tv.tv_usec = 0; }
+
+#ifdef UNICODE
+ wcstombs(strftimeex_m_tmpbuf, tstr, sizeof(strftimeex_m_tmpbuf));
+#else
+ memcpy(strftimeex_m_tmpbuf, tstr, sizeof(strftimeex_m_tmpbuf));
+#endif // UNICODE
+ strftimeex_m_tmpbuf[sizeof(strftimeex_m_tmpbuf)-sizeof(sztmp)-1] = 0;
+ free(tstr); tstr = NULL;
+#endif // !WINCE
+
+#ifndef DISABLE_USE_SNPRINTF
+ if (snprintf(sztmp, sizeof(sztmp), ":%02d", (int)(tv.tv_usec/10000)) != 3)
+#else
+ if (sprintf(sztmp, ":%02d", (int)(tv.tv_usec/10000)) != 3)
+#endif // DISABLE_USE_SNPRINTF
+ {
+ strcpy(sztmp, ":00");
+ }
+ strcat(strftimeex_fns_tmpbuf, sztmp);
+
+ return strftimeex_m_tmpbuf;
+}
+#endif // (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
+
/*
Return a string like ctime() but in this format :
@@ -203,7 +313,115 @@ char* strtime_fns(void)
#endif // UNICODE
strftime_fns_tmpbuf[sizeof(strftime_fns_tmpbuf)-1] = 0;
free(tstr); tstr = NULL;
-#endif // WINCE
+#endif // !WINCE
return strftime_fns_tmpbuf;
}
+
+#if (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
+/*
+Return a string like ctime() but in this format :
+
+2007-08-27_19h28min04s00\0
+
+(without the "\n", ":", " " of ctime() in order to be safely used in file names).
+Should not be used in concurrent threads as the string value returned might
+be changed by another thread.
+
+Return : This string.
+*/
+char* strtimeex_fns(void)
+{
+ char sztmp[3];
+ struct timeval tv;
+#ifndef WINCE
+ time_t tt;
+ struct tm *timeptr = NULL;
+
+ memset(strftimeex_fns_tmpbuf, 0, sizeof(strftimeex_fns_tmpbuf));
+
+ if (gettimeofday(&tv, NULL) != EXIT_SUCCESS) { tv.tv_sec = 0; tv.tv_usec = 0; time(&tt); }
+ else { tt = tv.tv_sec; }
+ timeptr = localtime(&tt);
+
+ if (timeptr == NULL)
+ {
+ return strftimeex_fns_tmpbuf;
+ }
+
+ // Use strftime to build a customized time string.
+ if (strftime(
+ strftimeex_fns_tmpbuf,
+ sizeof(strftimeex_fns_tmpbuf),
+ "%Y-%m-%d_%Hh%Mmin%Ss",
+ timeptr
+ ) <= 0)
+ {
+ memset(strftimeex_fns_tmpbuf, 0, sizeof(strftimeex_fns_tmpbuf));
+ return strftimeex_fns_tmpbuf;
+ }
+#else
+ int nb = 0;
+ TCHAR* tstr = (TCHAR*)calloc(sizeof(strftimeex_fns_tmpbuf), sizeof(TCHAR));
+
+ memset(strftimeex_fns_tmpbuf, 0, sizeof(strftimeex_fns_tmpbuf));
+
+ if (tstr == NULL)
+ {
+ return strftimeex_fns_tmpbuf;
+ }
+
+ memset(tstr, 0, sizeof(strftimeex_fns_tmpbuf)*sizeof(TCHAR));
+
+ // Use GetDateFormat() and GetTimeFormat() to build a customized time string.
+ nb = GetDateFormat(
+ MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), // Locale.
+ 0, // Flags.
+ NULL, // Current local system date.
+ _T("yyyy'-'MM'-'dd'_'"), // Format the string.
+ tstr,
+ sizeof(strftimeex_fns_tmpbuf)
+ );
+ if (nb <= 0)
+ {
+ free(tstr); tstr = NULL;
+ return strftimeex_fns_tmpbuf;
+ }
+
+ if (GetTimeFormat(
+ MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), // Locale.
+ 0, // Flags.
+ NULL, // Current local system time.
+ _T("HH'h'mm'min'ss's'"), // Format the string.
+ tstr+(nb-1),
+ sizeof(strftimeex_fns_tmpbuf)-(nb-1)
+ ) <= 0)
+ {
+ free(tstr); tstr = NULL;
+ return strftimeex_fns_tmpbuf;
+ }
+
+ if (gettimeofday(&tv, NULL) != EXIT_SUCCESS) { tv.tv_sec = 0; tv.tv_usec = 0; }
+
+#ifdef UNICODE
+ wcstombs(strftimeex_fns_tmpbuf, tstr, sizeof(strftimeex_fns_tmpbuf));
+#else
+ memcpy(strftimeex_fns_tmpbuf, tstr, sizeof(strftimeex_fns_tmpbuf));
+#endif // UNICODE
+ strftimeex_fns_tmpbuf[sizeof(strftimeex_fns_tmpbuf)-sizeof(sztmp)-1] = 0;
+ free(tstr); tstr = NULL;
+#endif // !WINCE
+
+#ifndef DISABLE_USE_SNPRINTF
+ if (snprintf(sztmp, sizeof(sztmp), "%02d", (int)(tv.tv_usec/10000)) != 2)
+#else
+ if (sprintf(sztmp, "%02d", (int)(tv.tv_usec/10000)) != 2)
+#endif // DISABLE_USE_SNPRINTF
+ {
+ strcpy(sztmp, "00");
+ }
+ strcat(strftimeex_fns_tmpbuf, sztmp);
+
+ return strftimeex_fns_tmpbuf;
+}
+#endif // (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
diff --git a/CamSvcSrv/jni/OSTime.h b/CamSvcSrv/jni/OSTime.h
index 4dbda6e..86f4944 100644
--- a/CamSvcSrv/jni/OSTime.h
+++ b/CamSvcSrv/jni/OSTime.h
@@ -69,7 +69,7 @@ Debug macros specific to OSTime.
#endif // ENABLE_GETTIMEOFDAY_WIN32
#else
#include
-#endif // ENABLE_SYS_TIME_H_WIN32
+#endif // !ENABLE_SYS_TIME_H_WIN32
#else
// CLOCK_MONOTONIC is a clock that cannot be set and represents monotonic time since
// some unspecified starting point.
@@ -77,11 +77,13 @@ Debug macros specific to OSTime.
// hardware-based time that is not subject to NTP adjustments.
#ifndef CLOCK_MONOTONIC_RAW
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
-#endif // CLOCK_MONOTONIC_RAW
+#endif // !CLOCK_MONOTONIC_RAW
#endif // _WIN32
EXTERN_C char strftime_m_tmpbuf[64]; // Used to store the string returned by strtime_m().
+EXTERN_C char strftimeex_m_tmpbuf[64]; // Used to store the string returned by strtimeex_m().
EXTERN_C char strftime_fns_tmpbuf[64]; // Used to store the string returned by strtime_fns().
+EXTERN_C char strftimeex_fns_tmpbuf[64]; // Used to store the string returned by strtimeex_fns().
#ifndef USE_OLD_CHRONO
#ifdef _WIN32
@@ -106,7 +108,9 @@ struct CHRONO
typedef struct CHRONO CHRONO;
#endif // _WIN32
#else
-#if defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32)
+// See https://stackoverflow.com/questions/43295845/is-the-clocks-per-sec-value-wrong-inside-a-virtual-machine
+#if (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
+//#if defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32)
/*
Structure for a basic chronometer.
Might not work correctly if used during more than approximately 68 years.
@@ -135,8 +139,9 @@ struct CHRONO
BOOL Suspended; // Used to know if the chronometer is currently suspended.
};
typedef struct CHRONO CHRONO;
-#endif // defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32)
-#endif // USE_OLD_CHRONO
+#endif // (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
+//#endif // defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32)
+#endif // !USE_OLD_CHRONO
#ifdef _WIN32
#ifndef ENABLE_SYS_TIME_H_WIN32
@@ -271,7 +276,7 @@ inline int gettimeofday(struct timeval* tv, struct timezone* tz)
// TVal->tv_usec = (unsigned int)(Ticks % 10000000) / 10;
//}
#endif // ENABLE_GETTIMEOFDAY_WIN32
-#endif // ENABLE_SYS_TIME_H_WIN32
+#endif // !ENABLE_SYS_TIME_H_WIN32
#endif // _WIN32
#ifndef _WIN32
@@ -290,36 +295,115 @@ inline DWORD GetTickCount(void)
return (DWORD)((tv.tv_sec*1000)+(tv.tv_usec/1000));
}
-#endif // _WIN32
+#endif // !_WIN32
// DWORD timeGetTime(void) is also similar to GetTickCount()...
#ifndef DISABLE_TIMEGM_MKGMTIME
#ifdef _WIN32
+#ifdef __GNUC__
+//#if !(((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
+// https://stackoverflow.com/questions/16647819/timegm-cross-platform
+//
+// Does not account for non-whole-hour offsets, for instance UTC?09:30, UTC+05:45, will fail
+// for time zones outside of +/-12 hours, will fail during hour when time zone is switched
+// from summer to winter, there is an ambiguity at those hour in local time because the same
+// local hour is used twice per night...
+//inline time_t _mkgmtime(struct tm * a_tm)
+//{
+// time_t ltime = mktime(a_tm);
+// struct tm tm_val;
+// gmtime_s(&tm_val, <ime);
+// int offset = (tm_val.tm_hour - a_tm->tm_hour);
+// if (offset > 12)
+// {
+// offset = 24 - offset;
+// }
+// time_t utc = mktime(a_tm) - offset * 3600;
+// return utc;
+//}
+
+inline int32_t __is_leap(int32_t year)
+{
+ if (year % 400 == 0)
+ return 1;
+ if (year % 100 == 0)
+ return 0;
+ if (year % 4 == 0)
+ return 1;
+ return 0;
+}
+
+inline int32_t __days_from_0(int32_t year)
+{
+ year--;
+ return 365 * year + (year / 400) - (year/100) + (year / 4);
+}
+inline int32_t __days_from_1970(int32_t year)
+{
+ int days_from_0_to_1970 = __days_from_0(1970);
+ return __days_from_0(year) - days_from_0_to_1970;
+}
+
+inline int32_t __days_from_1jan(int32_t year, int32_t month, int32_t day)
+{
+ static const int32_t days[2][12] =
+ {
+ { 0,31,59,90,120,151,181,212,243,273,304,334},
+ { 0,31,60,91,121,152,182,213,244,274,305,335}
+ };
+ return days[__is_leap(year)][month-1] + day - 1;
+}
+
+inline time_t timegm(struct tm * t)
+{
+ int year = t->tm_year + 1900;
+ int month = t->tm_mon;
+ if (month > 11)
+ {
+ year += month/12;
+ month %= 12;
+ }
+ else if (month < 0)
+ {
+ int years_diff = (-month + 11)/12;
+ year -= years_diff;
+ month += 12 * years_diff;
+ }
+ month++;
+ int day = t->tm_mday;
+ int day_of_year = __days_from_1jan(year, month, day);
+ int days_since_epoch = __days_from_1970(year) + day_of_year;
+
+ time_t seconds_in_day = 3600 * 24;
+ time_t result = seconds_in_day * days_since_epoch + 3600 * t->tm_hour + 60 * t->tm_min + t->tm_sec;
+
+ return result;
+}
+//#endif // !(((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4))
+#else
#ifndef WINCE
#ifndef timegm
#define timegm _mkgmtime
-#endif // timegm
+#endif // !timegm
// timelocal() is a deprecated interface that is equivalent to calling mktime() with a negative value for tm_isdst...
#ifndef timelocal
#define timelocal mktime
-#endif // timelocal
-#endif // WINCE
-
+#endif // !timelocal
+#endif // !WINCE
+#endif // __GNUC__
#else
-
#ifndef _mkgmtime
#define _mkgmtime timegm
-#endif // _mkgmtime
-
+#endif // !_mkgmtime
#endif // _WIN32
-#endif // DISABLE_TIMEGM_MKGMTIME
+#endif // !DISABLE_TIMEGM_MKGMTIME
/*
Return a string like ctime() but in this format :
-Mon Aug 27 19:28:04 2007\0
+2007-08-27 19:28:04\0
(without the "\n" of ctime()).
Should not be used directly in concurrent threads as the string value returned might
@@ -329,10 +413,25 @@ Return : This string.
*/
EXTERN_C char* strtime_m(void);
+#if (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
/*
Return a string like ctime() but in this format :
-Mon_Aug_27_19h28min04sec_2007\0
+2007-08-27 19:28:04:00\0
+
+(without the "\n" of ctime()).
+Should not be used directly in concurrent threads as the string value returned might
+be changed by another thread.
+
+Return : This string.
+*/
+EXTERN_C char* strtimeex_m(void);
+#endif // (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
+
+/*
+Return a string like ctime() but in this format :
+
+2007-08-27_19h28min04s\0
(without the "\n", ":", " " of ctime() in order to be safely used in file names).
Should not be used directly in concurrent threads as the string value returned might
@@ -342,6 +441,21 @@ Return : This string.
*/
EXTERN_C char* strtime_fns(void);
+#if (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
+/*
+Return a string like ctime() but in this format :
+
+2007-08-27_19h28min04s00\0
+
+(without the "\n", ":", " " of ctime() in order to be safely used in file names).
+Should not be used directly in concurrent threads as the string value returned might
+be changed by another thread.
+
+Return : This string.
+*/
+EXTERN_C char* strtimeex_fns(void);
+#endif // (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
+
/*
Wait some time...
@@ -364,6 +478,38 @@ inline void mSleep(long Milliseconds)
#endif // _WIN32
}
+/*
+Wait some time...
+
+long Microseconds : (IN) Time to wait in us.
+
+Return : Nothing.
+*/
+inline void uSleep(long Microseconds)
+{
+#ifdef _WIN32
+ // From https://stackoverflow.com/questions/5801813/c-usleep-is-obsolete-workarounds-for-windows-mingw.
+ HANDLE timer;
+ LARGE_INTEGER ft;
+
+ ft.QuadPart = -(10*(LONGLONG)Microseconds); // Convert to 100 nanosecond interval, negative value indicates relative time.
+
+ timer = CreateWaitableTimer(NULL, TRUE, NULL);
+ SetWaitableTimer(timer, &ft, 0, NULL, NULL, FALSE);
+ //WaitForSingleObject(timer, INFINITE);
+ WaitForSingleObject(timer, (DWORD)(1+Microseconds/1000));
+ CloseHandle(timer);
+#else
+ // usleep() is considered as obsolete.
+ //usleep(Microseconds);
+ struct timespec req;
+
+ req.tv_sec = Microseconds/1000000; // Seconds.
+ req.tv_nsec = (Microseconds%1000000)*1000; // Additional nanoseconds.
+ nanosleep(&req, NULL);
+#endif // _WIN32
+}
+
inline void DecSec2DaysHoursMinSec(double decsec, int* pDays, int* pHours, int* pMin, int* pSec, double* pDeccsec)
{
int hours = 0, minutes = 0, seconds = 0;
@@ -1022,7 +1168,9 @@ inline double StopChronoQuick(CHRONO* pChrono)
}
#endif // _WIN32
#else
-#if defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32)
+// See https://stackoverflow.com/questions/43295845/is-the-clocks-per-sec-value-wrong-inside-a-virtual-machine
+#if (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
+//#if defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32)
/*
Start a chronometer.
@@ -1614,7 +1762,8 @@ inline double StopChronoQuick(CHRONO* pChrono)
return pChrono->Duration;
}
}
-#endif // defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32)
-#endif // USE_OLD_CHRONO
+#endif // (defined(_WIN32) && (defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32))) || (!defined(_WIN32))
+//#endif // defined(ENABLE_GETTIMEOFDAY_WIN32) || defined(ENABLE_SYS_TIME_H_WIN32)
+#endif // !USE_OLD_CHRONO
-#endif // OSTIME_H
+#endif // !OSTIME_H
diff --git a/CamSvcSrv/project.properties b/CamSvcSrv/project.properties
index b880a84..414aeac 100644
--- a/CamSvcSrv/project.properties
+++ b/CamSvcSrv/project.properties
@@ -12,4 +12,4 @@
# Project target.
target=android-16
-android.library.reference.1=../OpenCV-2.4.9-android-sdk/sdk/java
+android.library.reference.1=../OpenCV-android-sdk/sdk/java
diff --git a/INFO_Android.txt b/INFO_Android.txt
index 8818818..5a8682b 100644
--- a/INFO_Android.txt
+++ b/INFO_Android.txt
@@ -16,7 +16,7 @@ Sleep : il faut utiliser les PARTIAL_WAKE_LOCK et android:keepScreenOn pour tout
Apps
-totalcommander et ses plugins réseaux, Bibus, Shazam, GPS Status, GPS Test, VNC Viewer, Adobe Reader, SMS Backup Restore, RAR, VLC, Facebook, Facebook Messenger, Orange TV, DroidEdit, Firefox, OS Monitor, Wifi Analyzer, Network Mapper, CoPilot GPS, My Sosh, SJCAM ZONE, SNCF, GitHub, u-center, CPU-Z, NoMachine, MATLAB, OpenVPN
+totalcommander et ses plugins réseaux, Bibus, Shazam, GPS Status, GPS Test, VNC Viewer, Adobe Reader, SMS Backup Restore, RAR, VLC, Facebook, Facebook Messenger, Orange TV, DroidEdit, Firefox, OS Monitor, Wifi Analyzer, Network Mapper, CoPilot GPS, My Sosh, SJCAM ZONE, SNCF, GitHub, u-center, CPU-Z, Moasure, Sound Meter, GStreamer Webcam, NoMachine, MATLAB, OpenVPN, GoPro, SwellCam, SwellPro Fly, OpenCPN, QGroundControl, NotifiCon, Discord, WhatsApp
DashLight, Stopwatch (équivalent parfois intégré)
Wireless Mic pour communiquer en audio entre 2 smartphones en Wi-Fi sans Internet
Google Maps/Chrome/Translate/YouTube/Docs/Slides/Sheets
diff --git a/ReadMe.txt b/ReadMe.txt
index 538d960..f5009c9 100644
--- a/ReadMe.txt
+++ b/ReadMe.txt
@@ -2,7 +2,7 @@ Description :
_ ASLogger : Enable to use a smartphone as a GPS tracker and AHRS. It records the GPS position, angles, speed, accelerations of the smartphone in Downloads/log.txt. This file can be imported in e.g. Microsoft Excel or in MATLAB and Google Earth using the tools provided in http://www.ensta-bretagne.fr/lebars/ASLogger_processing.zip. The GPS raw data are also recorded in Downloads/nmea.txt.
_ HelloIOIO : Modified version of the official IOIO sample to control 3 servomotors through the IOIO board connected to the smartphone.
_ BuggyTriangle : A buggy equipped with a smartphone and a IOIO board makes autonomously a triangle defined by 3 GPS points (to modify in the source code).
-_ CamSvcSrv : Enable to use a smartphone as an IP camera. Transfer smartphone camera image by Wi-Fi. You can use e.g. VLC (if MJPEG is selected in RemoteWebcamMultiSrv.txt) or RemoteWebcamCli to view in realtime the video on another computer of your Wi-Fi network. The configuration file should be put in Downloads/RemoteWebcamMultiSrv.txt on the smartphone (change the encoding and line endings to Linux standards). If your smartphone has several cameras, you might need to change the camera id in the configuration file. Check also the IP settings, disable firewall and antivirus if needed. See https://github.com/ENSTABretagneRobotics/RemoteWebcam for the Windows/Linux computer version. You might need to launch and kill the app 2-3 times before it works... Might not work on some smartphones or versions of Android due to OpenCV incompatibilities. Tested on a Samsung Galaxy S3 Mini with Android 4.1.2.
+_ CamSvcSrv : Enable to use a smartphone as an IP camera. Transfer smartphone camera images by Wi-Fi. You can use e.g. VLC (if MJPEG is selected in RemoteWebcamMultiSrv.txt) or RemoteWebcamCli to view in realtime the video on another computer of your Wi-Fi network. The configuration file should be put in Downloads/RemoteWebcamMultiSrv.txt on the smartphone (change the encoding and line endings to Linux standards). If your smartphone has several cameras, you might need to change the camera id in the configuration file. Check also the IP settings, disable firewall and antivirus if needed. See https://github.com/ENSTABretagneRobotics/RemoteWebcam for the Windows/Linux computer version. You might need to launch and kill the app 2-3 times before it works... Might not work on some smartphones or versions of Android due to OpenCV incompatibilities. Tested on a Samsung Galaxy S3 Mini with Android 4.1.2.
_ GPSSvcSrv : Enable to use a smartphone as an IP GPS on TCP port 4001. Use e.g. telnet to display raw data.
_ AHRSSvcSrv : Enable to use a smartphone as an IP Razor AHRS on TCP port 4007. Use e.g. telnet to display raw data.
_ IOIOSvcSrv : Enable to use a smartphone with a IOIO board as an IP SSC-32 on TCP port 4004. Use e.g. telnet to send SSC-32 commands (e.g. #0P1500).
@@ -18,6 +18,6 @@ Prerequisites (to be able to modify the code) :
_ See setup_android-sdk.pdf (and also http://www.ensta-bretagne.fr/lebars/)
_ App-IOIO0400 (for projects using the IOIO board, see https://github.com/ytai/ioio/raw/master/release/software/App-IOIO0400.zip)
_ android-ndk-r10e-windows-x86 (for projects using OpenCV)
-_ OpenCV-2.4.9-android-sdk (for projects using the camera)
+_ OpenCV-2.4.13-android-sdk (for projects using the camera, see https://docs.opencv.org/2.4/doc/tutorials/introduction/android_binary_package/android_dev_intro.html)
Copy the projects in your Eclipse workspace and in Eclipse choose Import Existing projects into workspace.
diff --git a/TODO.txt b/TODO.txt
index 873fa10..5976e63 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -25,7 +25,7 @@ ASLogger
difficile d'être sûr que les nombres seront bien dans le format 111111111.111 à cause des locales (séparateur décimal, séparateur milliers...)
renommer ASLogger en INSLog?
-C peut être compilé avec Code Sourcery arm-none-linux-gnueabi, compiler en static pour que ça puisse utiliser glibc car avec NDK ily a bionic à la place de glibc...
+C peut être compilé avec Code Sourcery arm-none-linux-gnueabi, compiler en static pour que ça puisse utiliser glibc car avec NDK il y a bionic à la place de glibc...
regarder threads ou autre de thibault, timer dans dossier android/smarttracker
timer ou Runnable and h2 Handler?