mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1046 lines
28 KiB
1046 lines
28 KiB
/*M/////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. |
|
// |
|
// By downloading, copying, installing or using the software you agree to this license. |
|
// If you do not agree to this license, do not download, install, |
|
// copy or use the software. |
|
// |
|
// |
|
// License Agreement |
|
// For Open Source Computer Vision Library |
|
// |
|
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. |
|
// Copyright (C) 2009, Willow Garage Inc., all rights reserved. |
|
// Third party copyrights are property of their respective owners. |
|
// |
|
// Redistribution and use in source and binary forms, with or without modification, |
|
// are permitted provided that the following conditions are met: |
|
// |
|
// * Redistribution's of source code must retain the above copyright notice, |
|
// this list of conditions and the following disclaimer. |
|
// |
|
// * Redistribution's in binary form must reproduce the above copyright notice, |
|
// this list of conditions and the following disclaimer in the documentation |
|
// and/or other materials provided with the distribution. |
|
// |
|
// * The name of the copyright holders may not be used to endorse or promote products |
|
// derived from this software without specific prior written permission. |
|
// |
|
// This software is provided by the copyright holders and contributors "as is" and |
|
// any express or implied warranties, including, but not limited to, the implied |
|
// warranties of merchantability and fitness for a particular purpose are disclaimed. |
|
// In no event shall the Intel Corporation or contributors be liable for any direct, |
|
// indirect, incidental, special, exemplary, or consequential damages |
|
// (including, but not limited to, procurement of substitute goods or services; |
|
// loss of use, data, or profits; or business interruption) however caused |
|
// and on any theory of liability, whether in contract, strict liability, |
|
// or tort (including negligence or otherwise) arising in any way out of |
|
// the use of this software, even if advised of the possibility of such damage. |
|
// |
|
//M*/ |
|
|
|
#include "precomp.hpp" |
|
|
|
#ifdef _MSC_VER |
|
# if _MSC_VER >= 1700 |
|
# pragma warning(disable:4447) // Disable warning 'main' signature found without threading model |
|
# endif |
|
#endif |
|
|
|
#if defined WIN32 || defined _WIN32 || defined WINCE |
|
#ifndef _WIN32_WINNT // This is needed for the declaration of TryEnterCriticalSection in winbase.h with Visual Studio 2005 (and older?) |
|
#define _WIN32_WINNT 0x0400 // http://msdn.microsoft.com/en-us/library/ms686857(VS.85).aspx |
|
#endif |
|
#include <windows.h> |
|
#if (_WIN32_WINNT >= 0x0602) |
|
#include <synchapi.h> |
|
#endif |
|
#undef small |
|
#undef min |
|
#undef max |
|
#undef abs |
|
#include <tchar.h> |
|
#if defined _MSC_VER |
|
#if _MSC_VER >= 1400 |
|
#include <intrin.h> |
|
#elif defined _M_IX86 |
|
static void __cpuid(int* cpuid_data, int) |
|
{ |
|
__asm |
|
{ |
|
push ebx |
|
push edi |
|
mov edi, cpuid_data |
|
mov eax, 1 |
|
cpuid |
|
mov [edi], eax |
|
mov [edi + 4], ebx |
|
mov [edi + 8], ecx |
|
mov [edi + 12], edx |
|
pop edi |
|
pop ebx |
|
} |
|
} |
|
#endif |
|
#endif |
|
|
|
#ifdef HAVE_WINRT |
|
#include <wrl/client.h> |
|
#ifndef __cplusplus_winrt |
|
#include <windows.storage.h> |
|
#pragma comment(lib, "runtimeobject.lib") |
|
#endif |
|
|
|
std::wstring GetTempPathWinRT() |
|
{ |
|
#ifdef __cplusplus_winrt |
|
return std::wstring(Windows::Storage::ApplicationData::Current->TemporaryFolder->Path->Data()); |
|
#else |
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationDataStatics> appdataFactory; |
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationData> appdataRef; |
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFolder> storagefolderRef; |
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageItem> storageitemRef; |
|
HSTRING str; |
|
HSTRING_HEADER hstrHead; |
|
std::wstring wstr; |
|
if (FAILED(WindowsCreateStringReference(RuntimeClass_Windows_Storage_ApplicationData, |
|
(UINT32)wcslen(RuntimeClass_Windows_Storage_ApplicationData), &hstrHead, &str))) |
|
return wstr; |
|
if (FAILED(Windows::Foundation::GetActivationFactory(str, appdataFactory.ReleaseAndGetAddressOf()))) |
|
return wstr; |
|
if (FAILED(appdataFactory->get_Current(appdataRef.ReleaseAndGetAddressOf()))) |
|
return wstr; |
|
if (FAILED(appdataRef->get_TemporaryFolder(storagefolderRef.ReleaseAndGetAddressOf()))) |
|
return wstr; |
|
if (FAILED(storagefolderRef.As(&storageitemRef))) |
|
return wstr; |
|
str = NULL; |
|
if (FAILED(storageitemRef->get_Path(&str))) |
|
return wstr; |
|
wstr = WindowsGetStringRawBuffer(str, NULL); |
|
WindowsDeleteString(str); |
|
return wstr; |
|
#endif |
|
} |
|
|
|
std::wstring GetTempFileNameWinRT(std::wstring prefix) |
|
{ |
|
wchar_t guidStr[40]; |
|
GUID g; |
|
CoCreateGuid(&g); |
|
wchar_t* mask = L"%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x"; |
|
swprintf(&guidStr[0], sizeof(guidStr)/sizeof(wchar_t), mask, |
|
g.Data1, g.Data2, g.Data3, UINT(g.Data4[0]), UINT(g.Data4[1]), |
|
UINT(g.Data4[2]), UINT(g.Data4[3]), UINT(g.Data4[4]), |
|
UINT(g.Data4[5]), UINT(g.Data4[6]), UINT(g.Data4[7])); |
|
|
|
return prefix + std::wstring(guidStr); |
|
} |
|
|
|
#endif |
|
#else |
|
#include <pthread.h> |
|
#include <sys/time.h> |
|
#include <time.h> |
|
|
|
#if defined __MACH__ && defined __APPLE__ |
|
#include <mach/mach.h> |
|
#include <mach/mach_time.h> |
|
#endif |
|
|
|
#endif |
|
|
|
#ifdef _OPENMP |
|
#include "omp.h" |
|
#endif |
|
|
|
#include <stdarg.h> |
|
|
|
#if defined __linux__ || defined __APPLE__ || defined __EMSCRIPTEN__ |
|
#include <unistd.h> |
|
#include <stdio.h> |
|
#include <sys/types.h> |
|
#if defined ANDROID |
|
#include <sys/sysconf.h> |
|
#else |
|
#include <sys/sysctl.h> |
|
#endif |
|
#endif |
|
|
|
#ifdef ANDROID |
|
# include <android/log.h> |
|
#endif |
|
|
|
namespace cv |
|
{ |
|
|
|
Exception::Exception() { code = 0; line = 0; } |
|
|
|
Exception::Exception(int _code, const String& _err, const String& _func, const String& _file, int _line) |
|
: code(_code), err(_err), func(_func), file(_file), line(_line) |
|
{ |
|
formatMessage(); |
|
} |
|
|
|
Exception::~Exception() throw() {} |
|
|
|
/*! |
|
\return the error description and the context as a text string. |
|
*/ |
|
const char* Exception::what() const throw() { return msg.c_str(); } |
|
|
|
void Exception::formatMessage() |
|
{ |
|
if( func.size() > 0 ) |
|
msg = format("%s:%d: error: (%d) %s in function %s\n", file.c_str(), line, code, err.c_str(), func.c_str()); |
|
else |
|
msg = format("%s:%d: error: (%d) %s\n", file.c_str(), line, code, err.c_str()); |
|
} |
|
|
|
struct HWFeatures |
|
{ |
|
enum { MAX_FEATURE = CV_HARDWARE_MAX_FEATURE }; |
|
|
|
HWFeatures(void) |
|
{ |
|
memset( have, 0, sizeof(have) ); |
|
x86_family = 0; |
|
} |
|
|
|
static HWFeatures initialize(void) |
|
{ |
|
HWFeatures f; |
|
int cpuid_data[4] = { 0, 0, 0, 0 }; |
|
|
|
#if defined _MSC_VER && (defined _M_IX86 || defined _M_X64) |
|
__cpuid(cpuid_data, 1); |
|
#elif defined __GNUC__ && (defined __i386__ || defined __x86_64__) |
|
#ifdef __x86_64__ |
|
asm __volatile__ |
|
( |
|
"movl $1, %%eax\n\t" |
|
"cpuid\n\t" |
|
:[eax]"=a"(cpuid_data[0]),[ebx]"=b"(cpuid_data[1]),[ecx]"=c"(cpuid_data[2]),[edx]"=d"(cpuid_data[3]) |
|
: |
|
: "cc" |
|
); |
|
#else |
|
asm volatile |
|
( |
|
"pushl %%ebx\n\t" |
|
"movl $1,%%eax\n\t" |
|
"cpuid\n\t" |
|
"popl %%ebx\n\t" |
|
: "=a"(cpuid_data[0]), "=c"(cpuid_data[2]), "=d"(cpuid_data[3]) |
|
: |
|
: "cc" |
|
); |
|
#endif |
|
#endif |
|
|
|
f.x86_family = (cpuid_data[0] >> 8) & 15; |
|
if( f.x86_family >= 6 ) |
|
{ |
|
f.have[CV_CPU_MMX] = (cpuid_data[3] & (1 << 23)) != 0; |
|
f.have[CV_CPU_SSE] = (cpuid_data[3] & (1<<25)) != 0; |
|
f.have[CV_CPU_SSE2] = (cpuid_data[3] & (1<<26)) != 0; |
|
f.have[CV_CPU_SSE3] = (cpuid_data[2] & (1<<0)) != 0; |
|
f.have[CV_CPU_SSSE3] = (cpuid_data[2] & (1<<9)) != 0; |
|
f.have[CV_CPU_SSE4_1] = (cpuid_data[2] & (1<<19)) != 0; |
|
f.have[CV_CPU_SSE4_2] = (cpuid_data[2] & (1<<20)) != 0; |
|
f.have[CV_CPU_POPCNT] = (cpuid_data[2] & (1<<23)) != 0; |
|
f.have[CV_CPU_AVX] = (((cpuid_data[2] & (1<<28)) != 0)&&((cpuid_data[2] & (1<<27)) != 0));//OS uses XSAVE_XRSTORE and CPU support AVX |
|
} |
|
|
|
return f; |
|
} |
|
|
|
int x86_family; |
|
bool have[MAX_FEATURE+1]; |
|
}; |
|
|
|
static HWFeatures featuresEnabled = HWFeatures::initialize(), featuresDisabled = HWFeatures(); |
|
static HWFeatures* currentFeatures = &featuresEnabled; |
|
|
|
bool checkHardwareSupport(int feature) |
|
{ |
|
CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE ); |
|
return currentFeatures->have[feature]; |
|
} |
|
|
|
|
|
volatile bool useOptimizedFlag = true; |
|
#ifdef HAVE_IPP |
|
struct IPPInitializer |
|
{ |
|
IPPInitializer(void) { ippStaticInit(); } |
|
}; |
|
|
|
IPPInitializer ippInitializer; |
|
#endif |
|
|
|
volatile bool USE_SSE2 = featuresEnabled.have[CV_CPU_SSE2]; |
|
volatile bool USE_SSE4_2 = featuresEnabled.have[CV_CPU_SSE4_2]; |
|
volatile bool USE_AVX = featuresEnabled.have[CV_CPU_AVX]; |
|
|
|
void setUseOptimized( bool flag ) |
|
{ |
|
useOptimizedFlag = flag; |
|
currentFeatures = flag ? &featuresEnabled : &featuresDisabled; |
|
USE_SSE2 = currentFeatures->have[CV_CPU_SSE2]; |
|
} |
|
|
|
bool useOptimized(void) |
|
{ |
|
return useOptimizedFlag; |
|
} |
|
|
|
int64 getTickCount(void) |
|
{ |
|
#if defined WIN32 || defined _WIN32 || defined WINCE |
|
LARGE_INTEGER counter; |
|
QueryPerformanceCounter( &counter ); |
|
return (int64)counter.QuadPart; |
|
#elif defined __linux || defined __linux__ |
|
struct timespec tp; |
|
clock_gettime(CLOCK_MONOTONIC, &tp); |
|
return (int64)tp.tv_sec*1000000000 + tp.tv_nsec; |
|
#elif defined __MACH__ && defined __APPLE__ |
|
return (int64)mach_absolute_time(); |
|
#else |
|
struct timeval tv; |
|
struct timezone tz; |
|
gettimeofday( &tv, &tz ); |
|
return (int64)tv.tv_sec*1000000 + tv.tv_usec; |
|
#endif |
|
} |
|
|
|
double getTickFrequency(void) |
|
{ |
|
#if defined WIN32 || defined _WIN32 || defined WINCE |
|
LARGE_INTEGER freq; |
|
QueryPerformanceFrequency(&freq); |
|
return (double)freq.QuadPart; |
|
#elif defined __linux || defined __linux__ |
|
return 1e9; |
|
#elif defined __MACH__ && defined __APPLE__ |
|
static double freq = 0; |
|
if( freq == 0 ) |
|
{ |
|
mach_timebase_info_data_t sTimebaseInfo; |
|
mach_timebase_info(&sTimebaseInfo); |
|
freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer; |
|
} |
|
return freq; |
|
#else |
|
return 1e6; |
|
#endif |
|
} |
|
|
|
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__) |
|
#if defined(__i386__) |
|
|
|
int64 getCPUTickCount(void) |
|
{ |
|
int64 x; |
|
__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); |
|
return x; |
|
} |
|
#elif defined(__x86_64__) |
|
|
|
int64 getCPUTickCount(void) |
|
{ |
|
unsigned hi, lo; |
|
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); |
|
return (int64)lo | ((int64)hi << 32); |
|
} |
|
|
|
#elif defined(__ppc__) |
|
|
|
int64 getCPUTickCount(void) |
|
{ |
|
int64 result = 0; |
|
unsigned upper, lower, tmp; |
|
__asm__ volatile( |
|
"0: \n" |
|
"\tmftbu %0 \n" |
|
"\tmftb %1 \n" |
|
"\tmftbu %2 \n" |
|
"\tcmpw %2,%0 \n" |
|
"\tbne 0b \n" |
|
: "=r"(upper),"=r"(lower),"=r"(tmp) |
|
); |
|
return lower | ((int64)upper << 32); |
|
} |
|
|
|
#else |
|
|
|
#error "RDTSC not defined" |
|
|
|
#endif |
|
|
|
#elif defined _MSC_VER && defined WIN32 && defined _M_IX86 |
|
|
|
int64 getCPUTickCount(void) |
|
{ |
|
__asm _emit 0x0f; |
|
__asm _emit 0x31; |
|
} |
|
|
|
#else |
|
|
|
#ifdef HAVE_IPP |
|
int64 getCPUTickCount(void) |
|
{ |
|
return ippGetCpuClocks(); |
|
} |
|
#else |
|
int64 getCPUTickCount(void) |
|
{ |
|
return getTickCount(); |
|
} |
|
#endif |
|
|
|
#endif |
|
|
|
const String& getBuildInformation() |
|
{ |
|
static String build_info = |
|
#include "version_string.inc" |
|
; |
|
return build_info; |
|
} |
|
|
|
String format( const char* fmt, ... ) |
|
{ |
|
char buf[1024]; |
|
|
|
va_list va; |
|
va_start(va, fmt); |
|
int len = vsnprintf(buf, sizeof(buf), fmt, va); |
|
va_end(va); |
|
|
|
if (len >= (int)sizeof(buf)) |
|
{ |
|
String s(len, '\0'); |
|
va_start(va, fmt); |
|
len = vsnprintf((char*)s.c_str(), len + 1, fmt, va); |
|
va_end(va); |
|
return s; |
|
} |
|
|
|
return String(buf, len); |
|
} |
|
|
|
String tempfile( const char* suffix ) |
|
{ |
|
#ifdef HAVE_WINRT |
|
std::wstring temp_dir = L""; |
|
const wchar_t* opencv_temp_dir = _wgetenv(L"OPENCV_TEMP_PATH"); |
|
if (opencv_temp_dir) |
|
temp_dir = std::wstring(opencv_temp_dir); |
|
#else |
|
const char *temp_dir = getenv("OPENCV_TEMP_PATH"); |
|
String fname; |
|
#endif |
|
|
|
#if defined WIN32 || defined _WIN32 |
|
#ifdef HAVE_WINRT |
|
RoInitialize(RO_INIT_MULTITHREADED); |
|
std::wstring temp_dir2; |
|
if (temp_dir.empty()) |
|
temp_dir = GetTempPathWinRT(); |
|
|
|
std::wstring temp_file; |
|
temp_file = GetTempFileNameWinRT(L"ocv"); |
|
if (temp_file.empty()) |
|
return std::string(); |
|
|
|
temp_file = temp_dir + std::wstring(L"\\") + temp_file; |
|
DeleteFileW(temp_file.c_str()); |
|
|
|
char aname[MAX_PATH]; |
|
size_t copied = wcstombs(aname, temp_file.c_str(), MAX_PATH); |
|
CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); |
|
fname = std::string(aname); |
|
RoUninitialize(); |
|
#else |
|
char temp_dir2[MAX_PATH] = { 0 }; |
|
char temp_file[MAX_PATH] = { 0 }; |
|
|
|
if (temp_dir == 0 || temp_dir[0] == 0) |
|
{ |
|
::GetTempPathA(sizeof(temp_dir2), temp_dir2); |
|
temp_dir = temp_dir2; |
|
} |
|
if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file)) |
|
return String(); |
|
|
|
DeleteFileA(temp_file); |
|
|
|
fname = temp_file; |
|
#endif |
|
# else |
|
# ifdef ANDROID |
|
//char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX"; |
|
char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX"; |
|
# else |
|
char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX"; |
|
# endif |
|
|
|
if (temp_dir == 0 || temp_dir[0] == 0) |
|
fname = defaultTemplate; |
|
else |
|
{ |
|
fname = temp_dir; |
|
char ech = fname[fname.size() - 1]; |
|
if(ech != '/' && ech != '\\') |
|
fname = fname + "/"; |
|
fname = fname + "__opencv_temp.XXXXXX"; |
|
} |
|
|
|
const int fd = mkstemp((char*)fname.c_str()); |
|
if (fd == -1) return String(); |
|
|
|
close(fd); |
|
remove(fname.c_str()); |
|
# endif |
|
|
|
if (suffix) |
|
{ |
|
if (suffix[0] != '.') |
|
return fname + "." + suffix; |
|
else |
|
return fname + suffix; |
|
} |
|
return fname; |
|
} |
|
|
|
static CvErrorCallback customErrorCallback = 0; |
|
static void* customErrorCallbackData = 0; |
|
static bool breakOnError = false; |
|
|
|
bool setBreakOnError(bool value) |
|
{ |
|
bool prevVal = breakOnError; |
|
breakOnError = value; |
|
return prevVal; |
|
} |
|
|
|
void error( const Exception& exc ) |
|
{ |
|
if (customErrorCallback != 0) |
|
customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(), |
|
exc.file.c_str(), exc.line, customErrorCallbackData); |
|
else |
|
{ |
|
const char* errorStr = cvErrorStr(exc.code); |
|
char buf[1 << 16]; |
|
|
|
sprintf( buf, "OpenCV Error: %s (%s) in %s, file %s, line %d", |
|
errorStr, exc.err.c_str(), exc.func.size() > 0 ? |
|
exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line ); |
|
fprintf( stderr, "%s\n", buf ); |
|
fflush( stderr ); |
|
# ifdef __ANDROID__ |
|
__android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf); |
|
# endif |
|
} |
|
|
|
if(breakOnError) |
|
{ |
|
static volatile int* p = 0; |
|
*p = 0; |
|
} |
|
|
|
throw exc; |
|
} |
|
|
|
void error(int _code, const String& _err, const char* _func, const char* _file, int _line) |
|
{ |
|
error(cv::Exception(_code, _err, _func, _file, _line)); |
|
} |
|
|
|
CvErrorCallback |
|
redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata) |
|
{ |
|
if( prevUserdata ) |
|
*prevUserdata = customErrorCallbackData; |
|
|
|
CvErrorCallback prevCallback = customErrorCallback; |
|
|
|
customErrorCallback = errCallback; |
|
customErrorCallbackData = userdata; |
|
|
|
return prevCallback; |
|
} |
|
|
|
} |
|
|
|
CV_IMPL int cvCheckHardwareSupport(int feature) |
|
{ |
|
CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE ); |
|
return cv::currentFeatures->have[feature]; |
|
} |
|
|
|
CV_IMPL int cvUseOptimized( int flag ) |
|
{ |
|
int prevMode = cv::useOptimizedFlag; |
|
cv::setUseOptimized( flag != 0 ); |
|
return prevMode; |
|
} |
|
|
|
CV_IMPL int64 cvGetTickCount(void) |
|
{ |
|
return cv::getTickCount(); |
|
} |
|
|
|
CV_IMPL double cvGetTickFrequency(void) |
|
{ |
|
return cv::getTickFrequency()*1e-6; |
|
} |
|
|
|
CV_IMPL CvErrorCallback |
|
cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata) |
|
{ |
|
return cv::redirectError(errCallback, userdata, prevUserdata); |
|
} |
|
|
|
CV_IMPL int cvNulDevReport( int, const char*, const char*, |
|
const char*, int, void* ) |
|
{ |
|
return 0; |
|
} |
|
|
|
CV_IMPL int cvStdErrReport( int, const char*, const char*, |
|
const char*, int, void* ) |
|
{ |
|
return 0; |
|
} |
|
|
|
CV_IMPL int cvGuiBoxReport( int, const char*, const char*, |
|
const char*, int, void* ) |
|
{ |
|
return 0; |
|
} |
|
|
|
CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* ) |
|
{ |
|
return 0; |
|
} |
|
|
|
|
|
CV_IMPL const char* cvErrorStr( int status ) |
|
{ |
|
static char buf[256]; |
|
|
|
switch (status) |
|
{ |
|
case CV_StsOk : return "No Error"; |
|
case CV_StsBackTrace : return "Backtrace"; |
|
case CV_StsError : return "Unspecified error"; |
|
case CV_StsInternal : return "Internal error"; |
|
case CV_StsNoMem : return "Insufficient memory"; |
|
case CV_StsBadArg : return "Bad argument"; |
|
case CV_StsNoConv : return "Iterations do not converge"; |
|
case CV_StsAutoTrace : return "Autotrace call"; |
|
case CV_StsBadSize : return "Incorrect size of input array"; |
|
case CV_StsNullPtr : return "Null pointer"; |
|
case CV_StsDivByZero : return "Division by zero occured"; |
|
case CV_BadStep : return "Image step is wrong"; |
|
case CV_StsInplaceNotSupported : return "Inplace operation is not supported"; |
|
case CV_StsObjectNotFound : return "Requested object was not found"; |
|
case CV_BadDepth : return "Input image depth is not supported by function"; |
|
case CV_StsUnmatchedFormats : return "Formats of input arguments do not match"; |
|
case CV_StsUnmatchedSizes : return "Sizes of input arguments do not match"; |
|
case CV_StsOutOfRange : return "One of arguments\' values is out of range"; |
|
case CV_StsUnsupportedFormat : return "Unsupported format or combination of formats"; |
|
case CV_BadCOI : return "Input COI is not supported"; |
|
case CV_BadNumChannels : return "Bad number of channels"; |
|
case CV_StsBadFlag : return "Bad flag (parameter or structure field)"; |
|
case CV_StsBadPoint : return "Bad parameter of type CvPoint"; |
|
case CV_StsBadMask : return "Bad type of mask argument"; |
|
case CV_StsParseError : return "Parsing error"; |
|
case CV_StsNotImplemented : return "The function/feature is not implemented"; |
|
case CV_StsBadMemBlock : return "Memory block has been corrupted"; |
|
case CV_StsAssert : return "Assertion failed"; |
|
case CV_GpuNotSupported : return "No CUDA support"; |
|
case CV_GpuApiCallError : return "Gpu API call"; |
|
case CV_OpenGlNotSupported : return "No OpenGL support"; |
|
case CV_OpenGlApiCallError : return "OpenGL API call"; |
|
}; |
|
|
|
sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status); |
|
return buf; |
|
} |
|
|
|
CV_IMPL int cvGetErrMode(void) |
|
{ |
|
return 0; |
|
} |
|
|
|
CV_IMPL int cvSetErrMode(int) |
|
{ |
|
return 0; |
|
} |
|
|
|
CV_IMPL int cvGetErrStatus(void) |
|
{ |
|
return 0; |
|
} |
|
|
|
CV_IMPL void cvSetErrStatus(int) |
|
{ |
|
} |
|
|
|
|
|
CV_IMPL void cvError( int code, const char* func_name, |
|
const char* err_msg, |
|
const char* file_name, int line ) |
|
{ |
|
cv::error(cv::Exception(code, err_msg, func_name, file_name, line)); |
|
} |
|
|
|
/* function, which converts int to int */ |
|
CV_IMPL int |
|
cvErrorFromIppStatus( int status ) |
|
{ |
|
switch (status) |
|
{ |
|
case CV_BADSIZE_ERR: return CV_StsBadSize; |
|
case CV_BADMEMBLOCK_ERR: return CV_StsBadMemBlock; |
|
case CV_NULLPTR_ERR: return CV_StsNullPtr; |
|
case CV_DIV_BY_ZERO_ERR: return CV_StsDivByZero; |
|
case CV_BADSTEP_ERR: return CV_BadStep; |
|
case CV_OUTOFMEM_ERR: return CV_StsNoMem; |
|
case CV_BADARG_ERR: return CV_StsBadArg; |
|
case CV_NOTDEFINED_ERR: return CV_StsError; |
|
case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported; |
|
case CV_NOTFOUND_ERR: return CV_StsObjectNotFound; |
|
case CV_BADCONVERGENCE_ERR: return CV_StsNoConv; |
|
case CV_BADDEPTH_ERR: return CV_BadDepth; |
|
case CV_UNMATCHED_FORMATS_ERR: return CV_StsUnmatchedFormats; |
|
case CV_UNSUPPORTED_COI_ERR: return CV_BadCOI; |
|
case CV_UNSUPPORTED_CHANNELS_ERR: return CV_BadNumChannels; |
|
case CV_BADFLAG_ERR: return CV_StsBadFlag; |
|
case CV_BADRANGE_ERR: return CV_StsBadArg; |
|
case CV_BADCOEF_ERR: return CV_StsBadArg; |
|
case CV_BADFACTOR_ERR: return CV_StsBadArg; |
|
case CV_BADPOINT_ERR: return CV_StsBadPoint; |
|
|
|
default: |
|
return CV_StsError; |
|
} |
|
} |
|
|
|
namespace cv { |
|
bool __termination = false; |
|
} |
|
|
|
namespace cv |
|
{ |
|
|
|
#if defined WIN32 || defined _WIN32 || defined WINCE |
|
|
|
struct Mutex::Impl |
|
{ |
|
Impl() |
|
{ |
|
#if (_WIN32_WINNT >= 0x0600) |
|
::InitializeCriticalSectionEx(&cs, 1000, 0); |
|
#else |
|
::InitializeCriticalSection(&cs); |
|
#endif |
|
refcount = 1; |
|
} |
|
~Impl() { DeleteCriticalSection(&cs); } |
|
|
|
void lock() { EnterCriticalSection(&cs); } |
|
bool trylock() { return TryEnterCriticalSection(&cs) != 0; } |
|
void unlock() { LeaveCriticalSection(&cs); } |
|
|
|
CRITICAL_SECTION cs; |
|
int refcount; |
|
}; |
|
|
|
#else |
|
|
|
struct Mutex::Impl |
|
{ |
|
Impl() |
|
{ |
|
pthread_mutexattr_t attr; |
|
pthread_mutexattr_init(&attr); |
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); |
|
pthread_mutex_init(&mt, &attr); |
|
pthread_mutexattr_destroy(&attr); |
|
|
|
refcount = 1; |
|
} |
|
~Impl() { pthread_mutex_destroy(&mt); } |
|
|
|
void lock() { pthread_mutex_lock(&mt); } |
|
bool trylock() { return pthread_mutex_trylock(&mt) == 0; } |
|
void unlock() { pthread_mutex_unlock(&mt); } |
|
|
|
pthread_mutex_t mt; |
|
int refcount; |
|
}; |
|
|
|
#endif |
|
|
|
Mutex::Mutex() |
|
{ |
|
impl = new Mutex::Impl; |
|
} |
|
|
|
Mutex::~Mutex() |
|
{ |
|
if( CV_XADD(&impl->refcount, -1) == 1 ) |
|
delete impl; |
|
impl = 0; |
|
} |
|
|
|
Mutex::Mutex(const Mutex& m) |
|
{ |
|
impl = m.impl; |
|
CV_XADD(&impl->refcount, 1); |
|
} |
|
|
|
Mutex& Mutex::operator = (const Mutex& m) |
|
{ |
|
CV_XADD(&m.impl->refcount, 1); |
|
if( CV_XADD(&impl->refcount, -1) == 1 ) |
|
delete impl; |
|
impl = m.impl; |
|
return *this; |
|
} |
|
|
|
void Mutex::lock() { impl->lock(); } |
|
void Mutex::unlock() { impl->unlock(); } |
|
bool Mutex::trylock() { return impl->trylock(); } |
|
|
|
|
|
//////////////////////////////// thread-local storage //////////////////////////////// |
|
|
|
class TLSStorage |
|
{ |
|
std::vector<void*> tlsData_; |
|
public: |
|
TLSStorage() { tlsData_.reserve(16); } |
|
~TLSStorage(); |
|
inline void* getData(int key) const |
|
{ |
|
CV_DbgAssert(key >= 0); |
|
return (key < (int)tlsData_.size()) ? tlsData_[key] : NULL; |
|
} |
|
inline void setData(int key, void* data) |
|
{ |
|
CV_DbgAssert(key >= 0); |
|
if (key >= (int)tlsData_.size()) |
|
{ |
|
tlsData_.resize(key + 1, NULL); |
|
} |
|
tlsData_[key] = data; |
|
} |
|
|
|
inline static TLSStorage* get(); |
|
}; |
|
|
|
#ifdef WIN32 |
|
#pragma warning(disable:4505) // unreferenced local function has been removed |
|
|
|
#ifdef HAVE_WINRT |
|
// using C++11 thread attribute for local thread data |
|
static __declspec( thread ) TLSStorage* g_tlsdata = NULL; |
|
|
|
static void deleteThreadData() |
|
{ |
|
if (g_tlsdata) |
|
{ |
|
delete g_tlsdata; |
|
g_tlsdata = NULL; |
|
} |
|
} |
|
|
|
inline TLSStorage* TLSStorage::get() |
|
{ |
|
if (!g_tlsdata) |
|
{ |
|
g_tlsdata = new TLSStorage; |
|
} |
|
return g_tlsdata; |
|
} |
|
#else |
|
#ifdef WINCE |
|
# define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF) |
|
#endif |
|
static DWORD tlsKey = TLS_OUT_OF_INDEXES; |
|
|
|
static void deleteThreadData() |
|
{ |
|
if(tlsKey != TLS_OUT_OF_INDEXES) |
|
{ |
|
delete (TLSStorage*)TlsGetValue(tlsKey); |
|
TlsSetValue(tlsKey, NULL); |
|
} |
|
} |
|
|
|
inline TLSStorage* TLSStorage::get() |
|
{ |
|
if (tlsKey == TLS_OUT_OF_INDEXES) |
|
{ |
|
tlsKey = TlsAlloc(); |
|
CV_Assert(tlsKey != TLS_OUT_OF_INDEXES); |
|
} |
|
TLSStorage* d = (TLSStorage*)TlsGetValue(tlsKey); |
|
if (!d) |
|
{ |
|
d = new TLSStorage; |
|
TlsSetValue(tlsKey, d); |
|
} |
|
return d; |
|
} |
|
#endif //HAVE_WINRT |
|
|
|
#if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE |
|
#ifdef HAVE_WINRT |
|
#pragma warning(disable:4447) // Disable warning 'main' signature found without threading model |
|
#endif |
|
|
|
BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID); |
|
|
|
BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved) |
|
{ |
|
if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH) |
|
{ |
|
if (lpReserved != NULL) // called after ExitProcess() call |
|
cv::__termination = true; |
|
cv::deleteThreadAllocData(); |
|
cv::deleteThreadData(); |
|
} |
|
return TRUE; |
|
} |
|
#endif |
|
|
|
#else |
|
static pthread_key_t tlsKey = 0; |
|
static pthread_once_t tlsKeyOnce = PTHREAD_ONCE_INIT; |
|
|
|
static void deleteTLSStorage(void* data) |
|
{ |
|
delete (TLSStorage*)data; |
|
} |
|
|
|
static void makeKey() |
|
{ |
|
int errcode = pthread_key_create(&tlsKey, deleteTLSStorage); |
|
CV_Assert(errcode == 0); |
|
} |
|
|
|
inline TLSStorage* TLSStorage::get() |
|
{ |
|
pthread_once(&tlsKeyOnce, makeKey); |
|
TLSStorage* d = (TLSStorage*)pthread_getspecific(tlsKey); |
|
if( !d ) |
|
{ |
|
d = new TLSStorage; |
|
pthread_setspecific(tlsKey, d); |
|
} |
|
return d; |
|
} |
|
#endif |
|
|
|
class TLSContainerStorage |
|
{ |
|
cv::Mutex mutex_; |
|
std::vector<TLSDataContainer*> tlsContainers_; |
|
public: |
|
TLSContainerStorage() { } |
|
~TLSContainerStorage() |
|
{ |
|
for (size_t i = 0; i < tlsContainers_.size(); i++) |
|
{ |
|
CV_DbgAssert(tlsContainers_[i] == NULL); // not all keys released |
|
tlsContainers_[i] = NULL; |
|
} |
|
} |
|
|
|
int allocateKey(TLSDataContainer* pContainer) |
|
{ |
|
cv::AutoLock lock(mutex_); |
|
tlsContainers_.push_back(pContainer); |
|
return (int)tlsContainers_.size() - 1; |
|
} |
|
void releaseKey(int id, TLSDataContainer* pContainer) |
|
{ |
|
cv::AutoLock lock(mutex_); |
|
CV_Assert(tlsContainers_[id] == pContainer); |
|
tlsContainers_[id] = NULL; |
|
// currently, we don't go into thread's TLSData and release data for this key |
|
} |
|
|
|
void destroyData(int key, void* data) |
|
{ |
|
cv::AutoLock lock(mutex_); |
|
TLSDataContainer* k = tlsContainers_[key]; |
|
if (!k) |
|
return; |
|
try |
|
{ |
|
k->deleteDataInstance(data); |
|
} |
|
catch (...) |
|
{ |
|
CV_DbgAssert(k == NULL); // Debug this! |
|
} |
|
} |
|
}; |
|
static TLSContainerStorage tlsContainerStorage; |
|
|
|
TLSDataContainer::TLSDataContainer() |
|
: key_(-1) |
|
{ |
|
key_ = tlsContainerStorage.allocateKey(this); |
|
} |
|
|
|
TLSDataContainer::~TLSDataContainer() |
|
{ |
|
tlsContainerStorage.releaseKey(key_, this); |
|
key_ = -1; |
|
} |
|
|
|
void* TLSDataContainer::getData() const |
|
{ |
|
CV_Assert(key_ >= 0); |
|
TLSStorage* tlsData = TLSStorage::get(); |
|
void* data = tlsData->getData(key_); |
|
if (!data) |
|
{ |
|
data = this->createDataInstance(); |
|
CV_DbgAssert(data != NULL); |
|
tlsData->setData(key_, data); |
|
} |
|
return data; |
|
} |
|
|
|
TLSStorage::~TLSStorage() |
|
{ |
|
for (int i = 0; i < (int)tlsData_.size(); i++) |
|
{ |
|
void*& data = tlsData_[i]; |
|
if (data) |
|
{ |
|
tlsContainerStorage.destroyData(i, data); |
|
data = NULL; |
|
} |
|
} |
|
tlsData_.clear(); |
|
} |
|
|
|
TLSData<CoreTLSData> coreTlsData; |
|
|
|
} // namespace cv |
|
|
|
/* End of file. */
|
|
|