1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
8 //
9 //
10 // License Agreement
11 // For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Copyright (C) 2015, Itseez Inc., all rights reserved.
16 // Third party copyrights are property of their respective owners.
17 //
18 // Redistribution and use in source and binary forms, with or without modification,
19 // are permitted provided that the following conditions are met:
20 //
21 // * Redistribution's of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // * Redistribution's in binary form must reproduce the above copyright notice,
25 // this list of conditions and the following disclaimer in the documentation
26 // and/or other materials provided with the distribution.
27 //
28 // * The name of the copyright holders may not be used to endorse or promote products
29 // derived from this software without specific prior written permission.
30 //
31 // This software is provided by the copyright holders and contributors "as is" and
32 // any express or implied warranties, including, but not limited to, the implied
33 // warranties of merchantability and fitness for a particular purpose are disclaimed.
34 // In no event shall the Intel Corporation or contributors be liable for any direct,
35 // indirect, incidental, special, exemplary, or consequential damages
36 // (including, but not limited to, procurement of substitute goods or services;
37 // loss of use, data, or profits; or business interruption) however caused
38 // and on any theory of liability, whether in contract, strict liability,
39 // or tort (including negligence or otherwise) arising in any way out of
40 // the use of this software, even if advised of the possibility of such damage.
41 //
42 //M*/
43
44 #include "precomp.hpp"
45
46 #ifdef _MSC_VER
47 # if _MSC_VER >= 1700
48 # pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
49 # endif
50 #endif
51
52 #if defined ANDROID || defined __linux__
53 # include <unistd.h>
54 # include <fcntl.h>
55 # include <elf.h>
56 # include <linux/auxvec.h>
57 #endif
58
59 #if defined WIN32 || defined _WIN32 || defined WINCE
60 #ifndef _WIN32_WINNT // This is needed for the declaration of TryEnterCriticalSection in winbase.h with Visual Studio 2005 (and older?)
61 #define _WIN32_WINNT 0x0400 // http://msdn.microsoft.com/en-us/library/ms686857(VS.85).aspx
62 #endif
63 #include <windows.h>
64 #if (_WIN32_WINNT >= 0x0602)
65 #include <synchapi.h>
66 #endif
67 #undef small
68 #undef min
69 #undef max
70 #undef abs
71 #include <tchar.h>
72 #if defined _MSC_VER
73 #if _MSC_VER >= 1400
74 #include <intrin.h>
75 #elif defined _M_IX86
__cpuid(int * cpuid_data,int)76 static void __cpuid(int* cpuid_data, int)
77 {
78 __asm
79 {
80 push ebx
81 push edi
82 mov edi, cpuid_data
83 mov eax, 1
84 cpuid
85 mov [edi], eax
86 mov [edi + 4], ebx
87 mov [edi + 8], ecx
88 mov [edi + 12], edx
89 pop edi
90 pop ebx
91 }
92 }
__cpuidex(int * cpuid_data,int,int)93 static void __cpuidex(int* cpuid_data, int, int)
94 {
95 __asm
96 {
97 push edi
98 mov edi, cpuid_data
99 mov eax, 7
100 mov ecx, 0
101 cpuid
102 mov [edi], eax
103 mov [edi + 4], ebx
104 mov [edi + 8], ecx
105 mov [edi + 12], edx
106 pop edi
107 }
108 }
109 #endif
110 #endif
111
112 #ifdef WINRT
113 #include <wrl/client.h>
114 #ifndef __cplusplus_winrt
115 #include <windows.storage.h>
116 #pragma comment(lib, "runtimeobject.lib")
117 #endif
118
GetTempPathWinRT()119 std::wstring GetTempPathWinRT()
120 {
121 #ifdef __cplusplus_winrt
122 return std::wstring(Windows::Storage::ApplicationData::Current->TemporaryFolder->Path->Data());
123 #else
124 Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationDataStatics> appdataFactory;
125 Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationData> appdataRef;
126 Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFolder> storagefolderRef;
127 Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageItem> storageitemRef;
128 HSTRING str;
129 HSTRING_HEADER hstrHead;
130 std::wstring wstr;
131 if (FAILED(WindowsCreateStringReference(RuntimeClass_Windows_Storage_ApplicationData,
132 (UINT32)wcslen(RuntimeClass_Windows_Storage_ApplicationData), &hstrHead, &str)))
133 return wstr;
134 if (FAILED(RoGetActivationFactory(str, IID_PPV_ARGS(appdataFactory.ReleaseAndGetAddressOf()))))
135 return wstr;
136 if (FAILED(appdataFactory->get_Current(appdataRef.ReleaseAndGetAddressOf())))
137 return wstr;
138 if (FAILED(appdataRef->get_TemporaryFolder(storagefolderRef.ReleaseAndGetAddressOf())))
139 return wstr;
140 if (FAILED(storagefolderRef.As(&storageitemRef)))
141 return wstr;
142 str = NULL;
143 if (FAILED(storageitemRef->get_Path(&str)))
144 return wstr;
145 wstr = WindowsGetStringRawBuffer(str, NULL);
146 WindowsDeleteString(str);
147 return wstr;
148 #endif
149 }
150
GetTempFileNameWinRT(std::wstring prefix)151 std::wstring GetTempFileNameWinRT(std::wstring prefix)
152 {
153 wchar_t guidStr[40];
154 GUID g;
155 CoCreateGuid(&g);
156 wchar_t* mask = L"%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x";
157 swprintf(&guidStr[0], sizeof(guidStr)/sizeof(wchar_t), mask,
158 g.Data1, g.Data2, g.Data3, UINT(g.Data4[0]), UINT(g.Data4[1]),
159 UINT(g.Data4[2]), UINT(g.Data4[3]), UINT(g.Data4[4]),
160 UINT(g.Data4[5]), UINT(g.Data4[6]), UINT(g.Data4[7]));
161
162 return prefix.append(std::wstring(guidStr));
163 }
164
165 #endif
166 #else
167 #include <pthread.h>
168 #include <sys/time.h>
169 #include <time.h>
170
171 #if defined __MACH__ && defined __APPLE__
172 #include <mach/mach.h>
173 #include <mach/mach_time.h>
174 #endif
175
176 #endif
177
178 #ifdef _OPENMP
179 #include "omp.h"
180 #endif
181
182 #include <stdarg.h>
183
184 #if defined __linux__ || defined __APPLE__ || defined __EMSCRIPTEN__
185 #include <unistd.h>
186 #include <stdio.h>
187 #include <sys/types.h>
188 #if defined ANDROID
189 #include <sys/sysconf.h>
190 #endif
191 #endif
192
193 #ifdef ANDROID
194 # include <android/log.h>
195 #endif
196
197 namespace cv
198 {
199
Exception()200 Exception::Exception() { code = 0; line = 0; }
201
Exception(int _code,const String & _err,const String & _func,const String & _file,int _line)202 Exception::Exception(int _code, const String& _err, const String& _func, const String& _file, int _line)
203 : code(_code), err(_err), func(_func), file(_file), line(_line)
204 {
205 formatMessage();
206 }
207
~Exception()208 Exception::~Exception() throw() {}
209
210 /*!
211 \return the error description and the context as a text string.
212 */
what() const213 const char* Exception::what() const throw() { return msg.c_str(); }
214
formatMessage()215 void Exception::formatMessage()
216 {
217 if( func.size() > 0 )
218 msg = format("%s:%d: error: (%d) %s in function %s\n", file.c_str(), line, code, err.c_str(), func.c_str());
219 else
220 msg = format("%s:%d: error: (%d) %s\n", file.c_str(), line, code, err.c_str());
221 }
222
223 struct HWFeatures
224 {
225 enum { MAX_FEATURE = CV_HARDWARE_MAX_FEATURE };
226
HWFeaturescv::HWFeatures227 HWFeatures(void)
228 {
229 memset( have, 0, sizeof(have) );
230 x86_family = 0;
231 }
232
initializecv::HWFeatures233 static HWFeatures initialize(void)
234 {
235 HWFeatures f;
236 int cpuid_data[4] = { 0, 0, 0, 0 };
237
238 #if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
239 __cpuid(cpuid_data, 1);
240 #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
241 #ifdef __x86_64__
242 asm __volatile__
243 (
244 "movl $1, %%eax\n\t"
245 "cpuid\n\t"
246 :[eax]"=a"(cpuid_data[0]),[ebx]"=b"(cpuid_data[1]),[ecx]"=c"(cpuid_data[2]),[edx]"=d"(cpuid_data[3])
247 :
248 : "cc"
249 );
250 #else
251 asm volatile
252 (
253 "pushl %%ebx\n\t"
254 "movl $1,%%eax\n\t"
255 "cpuid\n\t"
256 "popl %%ebx\n\t"
257 : "=a"(cpuid_data[0]), "=c"(cpuid_data[2]), "=d"(cpuid_data[3])
258 :
259 : "cc"
260 );
261 #endif
262 #endif
263
264 f.x86_family = (cpuid_data[0] >> 8) & 15;
265 if( f.x86_family >= 6 )
266 {
267 f.have[CV_CPU_MMX] = (cpuid_data[3] & (1 << 23)) != 0;
268 f.have[CV_CPU_SSE] = (cpuid_data[3] & (1<<25)) != 0;
269 f.have[CV_CPU_SSE2] = (cpuid_data[3] & (1<<26)) != 0;
270 f.have[CV_CPU_SSE3] = (cpuid_data[2] & (1<<0)) != 0;
271 f.have[CV_CPU_SSSE3] = (cpuid_data[2] & (1<<9)) != 0;
272 f.have[CV_CPU_FMA3] = (cpuid_data[2] & (1<<12)) != 0;
273 f.have[CV_CPU_SSE4_1] = (cpuid_data[2] & (1<<19)) != 0;
274 f.have[CV_CPU_SSE4_2] = (cpuid_data[2] & (1<<20)) != 0;
275 f.have[CV_CPU_POPCNT] = (cpuid_data[2] & (1<<23)) != 0;
276 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
277
278 // make the second call to the cpuid command in order to get
279 // information about extended features like AVX2
280 #if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
281 __cpuidex(cpuid_data, 7, 0);
282 #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
283 #ifdef __x86_64__
284 asm __volatile__
285 (
286 "movl $7, %%eax\n\t"
287 "movl $0, %%ecx\n\t"
288 "cpuid\n\t"
289 :[eax]"=a"(cpuid_data[0]),[ebx]"=b"(cpuid_data[1]),[ecx]"=c"(cpuid_data[2]),[edx]"=d"(cpuid_data[3])
290 :
291 : "cc"
292 );
293 #else
294 asm volatile
295 (
296 "pushl %%ebx\n\t"
297 "movl $7,%%eax\n\t"
298 "movl $0,%%ecx\n\t"
299 "cpuid\n\t"
300 "movl %%ebx, %0\n\t"
301 "popl %%ebx\n\t"
302 : "=r"(cpuid_data[1]), "=c"(cpuid_data[2])
303 :
304 : "cc"
305 );
306 #endif
307 #endif
308 f.have[CV_CPU_AVX2] = (cpuid_data[1] & (1<<5)) != 0;
309
310 f.have[CV_CPU_AVX_512F] = (cpuid_data[1] & (1<<16)) != 0;
311 f.have[CV_CPU_AVX_512DQ] = (cpuid_data[1] & (1<<17)) != 0;
312 f.have[CV_CPU_AVX_512IFMA512] = (cpuid_data[1] & (1<<21)) != 0;
313 f.have[CV_CPU_AVX_512PF] = (cpuid_data[1] & (1<<26)) != 0;
314 f.have[CV_CPU_AVX_512ER] = (cpuid_data[1] & (1<<27)) != 0;
315 f.have[CV_CPU_AVX_512CD] = (cpuid_data[1] & (1<<28)) != 0;
316 f.have[CV_CPU_AVX_512BW] = (cpuid_data[1] & (1<<30)) != 0;
317 f.have[CV_CPU_AVX_512VL] = (cpuid_data[1] & (1<<31)) != 0;
318 f.have[CV_CPU_AVX_512VBMI] = (cpuid_data[2] & (1<<1)) != 0;
319 }
320
321 #if defined ANDROID || defined __linux__
322 #ifdef __aarch64__
323 f.have[CV_CPU_NEON] = true;
324 #else
325 int cpufile = open("/proc/self/auxv", O_RDONLY);
326
327 if (cpufile >= 0)
328 {
329 Elf32_auxv_t auxv;
330 const size_t size_auxv_t = sizeof(auxv);
331
332 while ((size_t)read(cpufile, &auxv, size_auxv_t) == size_auxv_t)
333 {
334 if (auxv.a_type == AT_HWCAP)
335 {
336 f.have[CV_CPU_NEON] = (auxv.a_un.a_val & 4096) != 0;
337 break;
338 }
339 }
340
341 close(cpufile);
342 }
343 #endif
344 #elif (defined __clang__ || defined __APPLE__) && (defined __ARM_NEON__ || (defined __ARM_NEON && defined __aarch64__))
345 f.have[CV_CPU_NEON] = true;
346 #endif
347
348 return f;
349 }
350
351 int x86_family;
352 bool have[MAX_FEATURE+1];
353 };
354
355 static HWFeatures featuresEnabled = HWFeatures::initialize(), featuresDisabled = HWFeatures();
356 static HWFeatures* currentFeatures = &featuresEnabled;
357
checkHardwareSupport(int feature)358 bool checkHardwareSupport(int feature)
359 {
360 CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
361 return currentFeatures->have[feature];
362 }
363
364
365 volatile bool useOptimizedFlag = true;
366 #ifdef HAVE_IPP
367 struct IPPInitializer
368 {
IPPInitializercv::IPPInitializer369 IPPInitializer(void)
370 {
371 #if IPP_VERSION_MAJOR >= 8
372 ippInit();
373 #else
374 ippStaticInit();
375 #endif
376 }
377 };
378
379 IPPInitializer ippInitializer;
380 #endif
381
382 volatile bool USE_SSE2 = featuresEnabled.have[CV_CPU_SSE2];
383 volatile bool USE_SSE4_2 = featuresEnabled.have[CV_CPU_SSE4_2];
384 volatile bool USE_AVX = featuresEnabled.have[CV_CPU_AVX];
385 volatile bool USE_AVX2 = featuresEnabled.have[CV_CPU_AVX2];
386
setUseOptimized(bool flag)387 void setUseOptimized( bool flag )
388 {
389 useOptimizedFlag = flag;
390 currentFeatures = flag ? &featuresEnabled : &featuresDisabled;
391 USE_SSE2 = currentFeatures->have[CV_CPU_SSE2];
392
393 ipp::setUseIPP(flag);
394 ocl::setUseOpenCL(flag);
395 #ifdef HAVE_TEGRA_OPTIMIZATION
396 ::tegra::setUseTegra(flag);
397 #endif
398 }
399
useOptimized(void)400 bool useOptimized(void)
401 {
402 return useOptimizedFlag;
403 }
404
getTickCount(void)405 int64 getTickCount(void)
406 {
407 #if defined WIN32 || defined _WIN32 || defined WINCE
408 LARGE_INTEGER counter;
409 QueryPerformanceCounter( &counter );
410 return (int64)counter.QuadPart;
411 #elif defined __linux || defined __linux__
412 struct timespec tp;
413 clock_gettime(CLOCK_MONOTONIC, &tp);
414 return (int64)tp.tv_sec*1000000000 + tp.tv_nsec;
415 #elif defined __MACH__ && defined __APPLE__
416 return (int64)mach_absolute_time();
417 #else
418 struct timeval tv;
419 struct timezone tz;
420 gettimeofday( &tv, &tz );
421 return (int64)tv.tv_sec*1000000 + tv.tv_usec;
422 #endif
423 }
424
getTickFrequency(void)425 double getTickFrequency(void)
426 {
427 #if defined WIN32 || defined _WIN32 || defined WINCE
428 LARGE_INTEGER freq;
429 QueryPerformanceFrequency(&freq);
430 return (double)freq.QuadPart;
431 #elif defined __linux || defined __linux__
432 return 1e9;
433 #elif defined __MACH__ && defined __APPLE__
434 static double freq = 0;
435 if( freq == 0 )
436 {
437 mach_timebase_info_data_t sTimebaseInfo;
438 mach_timebase_info(&sTimebaseInfo);
439 freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer;
440 }
441 return freq;
442 #else
443 return 1e6;
444 #endif
445 }
446
447 #if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__)
448 #if defined(__i386__)
449
getCPUTickCount(void)450 int64 getCPUTickCount(void)
451 {
452 int64 x;
453 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
454 return x;
455 }
456 #elif defined(__x86_64__)
457
getCPUTickCount(void)458 int64 getCPUTickCount(void)
459 {
460 unsigned hi, lo;
461 __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
462 return (int64)lo | ((int64)hi << 32);
463 }
464
465 #elif defined(__ppc__)
466
getCPUTickCount(void)467 int64 getCPUTickCount(void)
468 {
469 int64 result = 0;
470 unsigned upper, lower, tmp;
471 __asm__ volatile(
472 "0: \n"
473 "\tmftbu %0 \n"
474 "\tmftb %1 \n"
475 "\tmftbu %2 \n"
476 "\tcmpw %2,%0 \n"
477 "\tbne 0b \n"
478 : "=r"(upper),"=r"(lower),"=r"(tmp)
479 );
480 return lower | ((int64)upper << 32);
481 }
482
483 #else
484
485 #error "RDTSC not defined"
486
487 #endif
488
489 #elif defined _MSC_VER && defined WIN32 && defined _M_IX86
490
getCPUTickCount(void)491 int64 getCPUTickCount(void)
492 {
493 __asm _emit 0x0f;
494 __asm _emit 0x31;
495 }
496
497 #else
498
499 //#ifdef HAVE_IPP
500 //int64 getCPUTickCount(void)
501 //{
502 // return ippGetCpuClocks();
503 //}
504 //#else
getCPUTickCount(void)505 int64 getCPUTickCount(void)
506 {
507 return getTickCount();
508 }
509 //#endif
510
511 #endif
512
getBuildInformation()513 const String& getBuildInformation()
514 {
515 static String build_info =
516 #include "version_string.inc"
517 ;
518 return build_info;
519 }
520
format(const char * fmt,...)521 String format( const char* fmt, ... )
522 {
523 AutoBuffer<char, 1024> buf;
524
525 for ( ; ; )
526 {
527 va_list va;
528 va_start(va, fmt);
529 int bsize = static_cast<int>(buf.size()),
530 len = vsnprintf((char *)buf, bsize, fmt, va);
531 va_end(va);
532
533 if (len < 0 || len >= bsize)
534 {
535 buf.resize(std::max(bsize << 1, len + 1));
536 continue;
537 }
538 return String((char *)buf, len);
539 }
540 }
541
tempfile(const char * suffix)542 String tempfile( const char* suffix )
543 {
544 String fname;
545 #ifndef WINRT
546 const char *temp_dir = getenv("OPENCV_TEMP_PATH");
547 #endif
548
549 #if defined WIN32 || defined _WIN32
550 #ifdef WINRT
551 RoInitialize(RO_INIT_MULTITHREADED);
552 std::wstring temp_dir = GetTempPathWinRT();
553
554 std::wstring temp_file = GetTempFileNameWinRT(L"ocv");
555 if (temp_file.empty())
556 return String();
557
558 temp_file = temp_dir.append(std::wstring(L"\\")).append(temp_file);
559 DeleteFileW(temp_file.c_str());
560
561 char aname[MAX_PATH];
562 size_t copied = wcstombs(aname, temp_file.c_str(), MAX_PATH);
563 CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
564 fname = String(aname);
565 RoUninitialize();
566 #else
567 char temp_dir2[MAX_PATH] = { 0 };
568 char temp_file[MAX_PATH] = { 0 };
569
570 if (temp_dir == 0 || temp_dir[0] == 0)
571 {
572 ::GetTempPathA(sizeof(temp_dir2), temp_dir2);
573 temp_dir = temp_dir2;
574 }
575 if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
576 return String();
577
578 DeleteFileA(temp_file);
579
580 fname = temp_file;
581 #endif
582 # else
583 # ifdef ANDROID
584 //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
585 char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX";
586 # else
587 char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
588 # endif
589
590 if (temp_dir == 0 || temp_dir[0] == 0)
591 fname = defaultTemplate;
592 else
593 {
594 fname = temp_dir;
595 char ech = fname[fname.size() - 1];
596 if(ech != '/' && ech != '\\')
597 fname = fname + "/";
598 fname = fname + "__opencv_temp.XXXXXX";
599 }
600
601 const int fd = mkstemp((char*)fname.c_str());
602 if (fd == -1) return String();
603
604 close(fd);
605 remove(fname.c_str());
606 # endif
607
608 if (suffix)
609 {
610 if (suffix[0] != '.')
611 return fname + "." + suffix;
612 else
613 return fname + suffix;
614 }
615 return fname;
616 }
617
618 static CvErrorCallback customErrorCallback = 0;
619 static void* customErrorCallbackData = 0;
620 static bool breakOnError = false;
621
setBreakOnError(bool value)622 bool setBreakOnError(bool value)
623 {
624 bool prevVal = breakOnError;
625 breakOnError = value;
626 return prevVal;
627 }
628
error(const Exception & exc)629 void error( const Exception& exc )
630 {
631 if (customErrorCallback != 0)
632 customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
633 exc.file.c_str(), exc.line, customErrorCallbackData);
634 else
635 {
636 const char* errorStr = cvErrorStr(exc.code);
637 char buf[1 << 16];
638
639 sprintf( buf, "OpenCV Error: %s (%s) in %s, file %s, line %d",
640 errorStr, exc.err.c_str(), exc.func.size() > 0 ?
641 exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line );
642 fprintf( stderr, "%s\n", buf );
643 fflush( stderr );
644 # ifdef __ANDROID__
645 __android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf);
646 # endif
647 }
648
649 if(breakOnError)
650 {
651 static volatile int* p = 0;
652 *p = 0;
653 }
654
655 throw exc;
656 }
657
error(int _code,const String & _err,const char * _func,const char * _file,int _line)658 void error(int _code, const String& _err, const char* _func, const char* _file, int _line)
659 {
660 error(cv::Exception(_code, _err, _func, _file, _line));
661 }
662
663 CvErrorCallback
redirectError(CvErrorCallback errCallback,void * userdata,void ** prevUserdata)664 redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
665 {
666 if( prevUserdata )
667 *prevUserdata = customErrorCallbackData;
668
669 CvErrorCallback prevCallback = customErrorCallback;
670
671 customErrorCallback = errCallback;
672 customErrorCallbackData = userdata;
673
674 return prevCallback;
675 }
676
677 }
678
cvCheckHardwareSupport(int feature)679 CV_IMPL int cvCheckHardwareSupport(int feature)
680 {
681 CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
682 return cv::currentFeatures->have[feature];
683 }
684
cvUseOptimized(int flag)685 CV_IMPL int cvUseOptimized( int flag )
686 {
687 int prevMode = cv::useOptimizedFlag;
688 cv::setUseOptimized( flag != 0 );
689 return prevMode;
690 }
691
cvGetTickCount(void)692 CV_IMPL int64 cvGetTickCount(void)
693 {
694 return cv::getTickCount();
695 }
696
cvGetTickFrequency(void)697 CV_IMPL double cvGetTickFrequency(void)
698 {
699 return cv::getTickFrequency()*1e-6;
700 }
701
702 CV_IMPL CvErrorCallback
cvRedirectError(CvErrorCallback errCallback,void * userdata,void ** prevUserdata)703 cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
704 {
705 return cv::redirectError(errCallback, userdata, prevUserdata);
706 }
707
cvNulDevReport(int,const char *,const char *,const char *,int,void *)708 CV_IMPL int cvNulDevReport( int, const char*, const char*,
709 const char*, int, void* )
710 {
711 return 0;
712 }
713
cvStdErrReport(int,const char *,const char *,const char *,int,void *)714 CV_IMPL int cvStdErrReport( int, const char*, const char*,
715 const char*, int, void* )
716 {
717 return 0;
718 }
719
cvGuiBoxReport(int,const char *,const char *,const char *,int,void *)720 CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
721 const char*, int, void* )
722 {
723 return 0;
724 }
725
cvGetErrInfo(const char **,const char **,const char **,int *)726 CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
727 {
728 return 0;
729 }
730
731
cvErrorStr(int status)732 CV_IMPL const char* cvErrorStr( int status )
733 {
734 static char buf[256];
735
736 switch (status)
737 {
738 case CV_StsOk : return "No Error";
739 case CV_StsBackTrace : return "Backtrace";
740 case CV_StsError : return "Unspecified error";
741 case CV_StsInternal : return "Internal error";
742 case CV_StsNoMem : return "Insufficient memory";
743 case CV_StsBadArg : return "Bad argument";
744 case CV_StsNoConv : return "Iterations do not converge";
745 case CV_StsAutoTrace : return "Autotrace call";
746 case CV_StsBadSize : return "Incorrect size of input array";
747 case CV_StsNullPtr : return "Null pointer";
748 case CV_StsDivByZero : return "Division by zero occured";
749 case CV_BadStep : return "Image step is wrong";
750 case CV_StsInplaceNotSupported : return "Inplace operation is not supported";
751 case CV_StsObjectNotFound : return "Requested object was not found";
752 case CV_BadDepth : return "Input image depth is not supported by function";
753 case CV_StsUnmatchedFormats : return "Formats of input arguments do not match";
754 case CV_StsUnmatchedSizes : return "Sizes of input arguments do not match";
755 case CV_StsOutOfRange : return "One of arguments\' values is out of range";
756 case CV_StsUnsupportedFormat : return "Unsupported format or combination of formats";
757 case CV_BadCOI : return "Input COI is not supported";
758 case CV_BadNumChannels : return "Bad number of channels";
759 case CV_StsBadFlag : return "Bad flag (parameter or structure field)";
760 case CV_StsBadPoint : return "Bad parameter of type CvPoint";
761 case CV_StsBadMask : return "Bad type of mask argument";
762 case CV_StsParseError : return "Parsing error";
763 case CV_StsNotImplemented : return "The function/feature is not implemented";
764 case CV_StsBadMemBlock : return "Memory block has been corrupted";
765 case CV_StsAssert : return "Assertion failed";
766 case CV_GpuNotSupported : return "No CUDA support";
767 case CV_GpuApiCallError : return "Gpu API call";
768 case CV_OpenGlNotSupported : return "No OpenGL support";
769 case CV_OpenGlApiCallError : return "OpenGL API call";
770 };
771
772 sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
773 return buf;
774 }
775
cvGetErrMode(void)776 CV_IMPL int cvGetErrMode(void)
777 {
778 return 0;
779 }
780
cvSetErrMode(int)781 CV_IMPL int cvSetErrMode(int)
782 {
783 return 0;
784 }
785
cvGetErrStatus(void)786 CV_IMPL int cvGetErrStatus(void)
787 {
788 return 0;
789 }
790
cvSetErrStatus(int)791 CV_IMPL void cvSetErrStatus(int)
792 {
793 }
794
795
cvError(int code,const char * func_name,const char * err_msg,const char * file_name,int line)796 CV_IMPL void cvError( int code, const char* func_name,
797 const char* err_msg,
798 const char* file_name, int line )
799 {
800 cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
801 }
802
803 /* function, which converts int to int */
804 CV_IMPL int
cvErrorFromIppStatus(int status)805 cvErrorFromIppStatus( int status )
806 {
807 switch (status)
808 {
809 case CV_BADSIZE_ERR: return CV_StsBadSize;
810 case CV_BADMEMBLOCK_ERR: return CV_StsBadMemBlock;
811 case CV_NULLPTR_ERR: return CV_StsNullPtr;
812 case CV_DIV_BY_ZERO_ERR: return CV_StsDivByZero;
813 case CV_BADSTEP_ERR: return CV_BadStep;
814 case CV_OUTOFMEM_ERR: return CV_StsNoMem;
815 case CV_BADARG_ERR: return CV_StsBadArg;
816 case CV_NOTDEFINED_ERR: return CV_StsError;
817 case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported;
818 case CV_NOTFOUND_ERR: return CV_StsObjectNotFound;
819 case CV_BADCONVERGENCE_ERR: return CV_StsNoConv;
820 case CV_BADDEPTH_ERR: return CV_BadDepth;
821 case CV_UNMATCHED_FORMATS_ERR: return CV_StsUnmatchedFormats;
822 case CV_UNSUPPORTED_COI_ERR: return CV_BadCOI;
823 case CV_UNSUPPORTED_CHANNELS_ERR: return CV_BadNumChannels;
824 case CV_BADFLAG_ERR: return CV_StsBadFlag;
825 case CV_BADRANGE_ERR: return CV_StsBadArg;
826 case CV_BADCOEF_ERR: return CV_StsBadArg;
827 case CV_BADFACTOR_ERR: return CV_StsBadArg;
828 case CV_BADPOINT_ERR: return CV_StsBadPoint;
829
830 default:
831 return CV_StsError;
832 }
833 }
834
835 namespace cv {
836 bool __termination = false;
837 }
838
839 namespace cv
840 {
841
842 #if defined WIN32 || defined _WIN32 || defined WINCE
843
844 struct Mutex::Impl
845 {
Implcv::Mutex::Impl846 Impl()
847 {
848 #if (_WIN32_WINNT >= 0x0600)
849 ::InitializeCriticalSectionEx(&cs, 1000, 0);
850 #else
851 ::InitializeCriticalSection(&cs);
852 #endif
853 refcount = 1;
854 }
~Implcv::Mutex::Impl855 ~Impl() { DeleteCriticalSection(&cs); }
856
lockcv::Mutex::Impl857 void lock() { EnterCriticalSection(&cs); }
trylockcv::Mutex::Impl858 bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
unlockcv::Mutex::Impl859 void unlock() { LeaveCriticalSection(&cs); }
860
861 CRITICAL_SECTION cs;
862 int refcount;
863 };
864
865 #else
866
867 struct Mutex::Impl
868 {
869 Impl()
870 {
871 pthread_mutexattr_t attr;
872 pthread_mutexattr_init(&attr);
873 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
874 pthread_mutex_init(&mt, &attr);
875 pthread_mutexattr_destroy(&attr);
876
877 refcount = 1;
878 }
879 ~Impl() { pthread_mutex_destroy(&mt); }
880
881 void lock() { pthread_mutex_lock(&mt); }
882 bool trylock() { return pthread_mutex_trylock(&mt) == 0; }
883 void unlock() { pthread_mutex_unlock(&mt); }
884
885 pthread_mutex_t mt;
886 int refcount;
887 };
888
889 #endif
890
Mutex()891 Mutex::Mutex()
892 {
893 impl = new Mutex::Impl;
894 }
895
~Mutex()896 Mutex::~Mutex()
897 {
898 if( CV_XADD(&impl->refcount, -1) == 1 )
899 delete impl;
900 impl = 0;
901 }
902
Mutex(const Mutex & m)903 Mutex::Mutex(const Mutex& m)
904 {
905 impl = m.impl;
906 CV_XADD(&impl->refcount, 1);
907 }
908
operator =(const Mutex & m)909 Mutex& Mutex::operator = (const Mutex& m)
910 {
911 CV_XADD(&m.impl->refcount, 1);
912 if( CV_XADD(&impl->refcount, -1) == 1 )
913 delete impl;
914 impl = m.impl;
915 return *this;
916 }
917
lock()918 void Mutex::lock() { impl->lock(); }
unlock()919 void Mutex::unlock() { impl->unlock(); }
trylock()920 bool Mutex::trylock() { return impl->trylock(); }
921
922
923 //////////////////////////////// thread-local storage ////////////////////////////////
924
925 class TLSStorage
926 {
927 std::vector<void*> tlsData_;
928 public:
TLSStorage()929 TLSStorage() { tlsData_.reserve(16); }
930 ~TLSStorage();
getData(int key) const931 inline void* getData(int key) const
932 {
933 CV_DbgAssert(key >= 0);
934 return (key < (int)tlsData_.size()) ? tlsData_[key] : NULL;
935 }
setData(int key,void * data)936 inline void setData(int key, void* data)
937 {
938 CV_DbgAssert(key >= 0);
939 if (key >= (int)tlsData_.size())
940 {
941 tlsData_.resize(key + 1, NULL);
942 }
943 tlsData_[key] = data;
944 }
945
946 inline static TLSStorage* get();
947 };
948
949 #ifdef WIN32
950 #ifdef _MSC_VER
951 #pragma warning(disable:4505) // unreferenced local function has been removed
952 #endif
953
954 #ifdef WINRT
955 // using C++11 thread attribute for local thread data
956 static __declspec( thread ) TLSStorage* g_tlsdata = NULL;
957
deleteThreadData()958 static void deleteThreadData()
959 {
960 if (g_tlsdata)
961 {
962 delete g_tlsdata;
963 g_tlsdata = NULL;
964 }
965 }
966
get()967 inline TLSStorage* TLSStorage::get()
968 {
969 if (!g_tlsdata)
970 {
971 g_tlsdata = new TLSStorage;
972 }
973 return g_tlsdata;
974 }
975 #else
976 #ifdef WINCE
977 # define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
978 #endif
979 static DWORD tlsKey = TLS_OUT_OF_INDEXES;
980
deleteThreadData()981 static void deleteThreadData()
982 {
983 if(tlsKey != TLS_OUT_OF_INDEXES)
984 {
985 delete (TLSStorage*)TlsGetValue(tlsKey);
986 TlsSetValue(tlsKey, NULL);
987 }
988 }
989
get()990 inline TLSStorage* TLSStorage::get()
991 {
992 if (tlsKey == TLS_OUT_OF_INDEXES)
993 {
994 tlsKey = TlsAlloc();
995 CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
996 }
997 TLSStorage* d = (TLSStorage*)TlsGetValue(tlsKey);
998 if (!d)
999 {
1000 d = new TLSStorage;
1001 TlsSetValue(tlsKey, d);
1002 }
1003 return d;
1004 }
1005 #endif //WINRT
1006
1007 #if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE
1008 #ifdef WINRT
1009 #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
1010 #endif
1011
1012 extern "C"
DllMain(HINSTANCE,DWORD fdwReason,LPVOID lpReserved)1013 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved)
1014 {
1015 if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH)
1016 {
1017 if (lpReserved != NULL) // called after ExitProcess() call
1018 {
1019 cv::__termination = true;
1020 }
1021 else
1022 {
1023 // Not allowed to free resources if lpReserved is non-null
1024 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583.aspx
1025 cv::deleteThreadAllocData();
1026 cv::deleteThreadData();
1027 }
1028 }
1029 return TRUE;
1030 }
1031 #endif
1032
1033 #else
1034 static pthread_key_t tlsKey = 0;
1035 static pthread_once_t tlsKeyOnce = PTHREAD_ONCE_INIT;
1036
deleteTLSStorage(void * data)1037 static void deleteTLSStorage(void* data)
1038 {
1039 delete (TLSStorage*)data;
1040 }
1041
makeKey()1042 static void makeKey()
1043 {
1044 int errcode = pthread_key_create(&tlsKey, deleteTLSStorage);
1045 CV_Assert(errcode == 0);
1046 }
1047
get()1048 inline TLSStorage* TLSStorage::get()
1049 {
1050 pthread_once(&tlsKeyOnce, makeKey);
1051 TLSStorage* d = (TLSStorage*)pthread_getspecific(tlsKey);
1052 if( !d )
1053 {
1054 d = new TLSStorage;
1055 pthread_setspecific(tlsKey, d);
1056 }
1057 return d;
1058 }
1059 #endif
1060
1061 class TLSContainerStorage
1062 {
1063 cv::Mutex mutex_;
1064 std::vector<TLSDataContainer*> tlsContainers_;
1065 public:
TLSContainerStorage()1066 TLSContainerStorage() { }
~TLSContainerStorage()1067 ~TLSContainerStorage()
1068 {
1069 for (size_t i = 0; i < tlsContainers_.size(); i++)
1070 {
1071 CV_DbgAssert(tlsContainers_[i] == NULL); // not all keys released
1072 tlsContainers_[i] = NULL;
1073 }
1074 }
1075
allocateKey(TLSDataContainer * pContainer)1076 int allocateKey(TLSDataContainer* pContainer)
1077 {
1078 cv::AutoLock lock(mutex_);
1079 tlsContainers_.push_back(pContainer);
1080 return (int)tlsContainers_.size() - 1;
1081 }
releaseKey(int id,TLSDataContainer * pContainer)1082 void releaseKey(int id, TLSDataContainer* pContainer)
1083 {
1084 cv::AutoLock lock(mutex_);
1085 CV_Assert(tlsContainers_[id] == pContainer);
1086 tlsContainers_[id] = NULL;
1087 // currently, we don't go into thread's TLSData and release data for this key
1088 }
1089
destroyData(int key,void * data)1090 void destroyData(int key, void* data)
1091 {
1092 cv::AutoLock lock(mutex_);
1093 TLSDataContainer* k = tlsContainers_[key];
1094 if (!k)
1095 return;
1096 try
1097 {
1098 k->deleteDataInstance(data);
1099 }
1100 catch (...)
1101 {
1102 CV_DbgAssert(k == NULL); // Debug this!
1103 }
1104 }
1105 };
1106
1107 // This is a wrapper function that will ensure 'tlsContainerStorage' is constructed on first use.
1108 // For more information: http://www.parashift.com/c++-faq/static-init-order-on-first-use.html
getTLSContainerStorage()1109 static TLSContainerStorage& getTLSContainerStorage()
1110 {
1111 static TLSContainerStorage *tlsContainerStorage = new TLSContainerStorage();
1112 return *tlsContainerStorage;
1113 }
1114
TLSDataContainer()1115 TLSDataContainer::TLSDataContainer()
1116 : key_(-1)
1117 {
1118 key_ = getTLSContainerStorage().allocateKey(this);
1119 }
1120
~TLSDataContainer()1121 TLSDataContainer::~TLSDataContainer()
1122 {
1123 getTLSContainerStorage().releaseKey(key_, this);
1124 key_ = -1;
1125 }
1126
getData() const1127 void* TLSDataContainer::getData() const
1128 {
1129 CV_Assert(key_ >= 0);
1130 TLSStorage* tlsData = TLSStorage::get();
1131 void* data = tlsData->getData(key_);
1132 if (!data)
1133 {
1134 data = this->createDataInstance();
1135 CV_DbgAssert(data != NULL);
1136 tlsData->setData(key_, data);
1137 }
1138 return data;
1139 }
1140
~TLSStorage()1141 TLSStorage::~TLSStorage()
1142 {
1143 for (int i = 0; i < (int)tlsData_.size(); i++)
1144 {
1145 void*& data = tlsData_[i];
1146 if (data)
1147 {
1148 getTLSContainerStorage().destroyData(i, data);
1149 data = NULL;
1150 }
1151 }
1152 tlsData_.clear();
1153 }
1154
1155
1156
getCoreTlsData()1157 TLSData<CoreTLSData>& getCoreTlsData()
1158 {
1159 static TLSData<CoreTLSData> *value = new TLSData<CoreTLSData>();
1160 return *value;
1161 }
1162
1163
1164
1165 #ifdef CV_COLLECT_IMPL_DATA
getImplData()1166 ImplCollector& getImplData()
1167 {
1168 static ImplCollector *value = new ImplCollector();
1169 return *value;
1170 }
1171
setImpl(int flags)1172 void setImpl(int flags)
1173 {
1174 cv::AutoLock lock(getImplData().mutex);
1175
1176 getImplData().implFlags = flags;
1177 getImplData().implCode.clear();
1178 getImplData().implFun.clear();
1179 }
1180
addImpl(int flag,const char * func)1181 void addImpl(int flag, const char* func)
1182 {
1183 cv::AutoLock lock(getImplData().mutex);
1184
1185 getImplData().implFlags |= flag;
1186 if(func) // use lazy collection if name was not specified
1187 {
1188 size_t index = getImplData().implCode.size();
1189 if(!index || (getImplData().implCode[index-1] != flag || getImplData().implFun[index-1].compare(func))) // avoid duplicates
1190 {
1191 getImplData().implCode.push_back(flag);
1192 getImplData().implFun.push_back(func);
1193 }
1194 }
1195 }
1196
getImpl(std::vector<int> & impl,std::vector<String> & funName)1197 int getImpl(std::vector<int> &impl, std::vector<String> &funName)
1198 {
1199 cv::AutoLock lock(getImplData().mutex);
1200
1201 impl = getImplData().implCode;
1202 funName = getImplData().implFun;
1203 return getImplData().implFlags; // return actual flags for lazy collection
1204 }
1205
useCollection()1206 bool useCollection()
1207 {
1208 return getImplData().useCollection;
1209 }
1210
setUseCollection(bool flag)1211 void setUseCollection(bool flag)
1212 {
1213 cv::AutoLock lock(getImplData().mutex);
1214
1215 getImplData().useCollection = flag;
1216 }
1217 #endif
1218
1219 namespace ipp
1220 {
1221
1222 static int ippStatus = 0; // 0 - all is ok, -1 - IPP functions failed
1223 static const char * funcname = NULL, * filename = NULL;
1224 static int linen = 0;
1225
setIppStatus(int status,const char * const _funcname,const char * const _filename,int _line)1226 void setIppStatus(int status, const char * const _funcname, const char * const _filename, int _line)
1227 {
1228 ippStatus = status;
1229 funcname = _funcname;
1230 filename = _filename;
1231 linen = _line;
1232 }
1233
getIppStatus()1234 int getIppStatus()
1235 {
1236 return ippStatus;
1237 }
1238
getIppErrorLocation()1239 String getIppErrorLocation()
1240 {
1241 return format("%s:%d %s", filename ? filename : "", linen, funcname ? funcname : "");
1242 }
1243
useIPP()1244 bool useIPP()
1245 {
1246 #ifdef HAVE_IPP
1247 CoreTLSData* data = getCoreTlsData().get();
1248 if(data->useIPP < 0)
1249 {
1250 const char* pIppEnv = getenv("OPENCV_IPP");
1251 if(pIppEnv && (cv::String(pIppEnv) == "disabled"))
1252 data->useIPP = false;
1253 else
1254 data->useIPP = true;
1255 }
1256 return (data->useIPP > 0);
1257 #else
1258 return false;
1259 #endif
1260 }
1261
setUseIPP(bool flag)1262 void setUseIPP(bool flag)
1263 {
1264 CoreTLSData* data = getCoreTlsData().get();
1265 #ifdef HAVE_IPP
1266 data->useIPP = flag;
1267 #else
1268 (void)flag;
1269 data->useIPP = false;
1270 #endif
1271 }
1272
1273 } // namespace ipp
1274
1275 } // namespace cv
1276
1277 #ifdef HAVE_TEGRA_OPTIMIZATION
1278
1279 namespace tegra {
1280
useTegra()1281 bool useTegra()
1282 {
1283 cv::CoreTLSData* data = cv::getCoreTlsData().get();
1284
1285 if (data->useTegra < 0)
1286 {
1287 const char* pTegraEnv = getenv("OPENCV_TEGRA");
1288 if (pTegraEnv && (cv::String(pTegraEnv) == "disabled"))
1289 data->useTegra = false;
1290 else
1291 data->useTegra = true;
1292 }
1293
1294 return (data->useTegra > 0);
1295 }
1296
setUseTegra(bool flag)1297 void setUseTegra(bool flag)
1298 {
1299 cv::CoreTLSData* data = cv::getCoreTlsData().get();
1300 data->useTegra = flag;
1301 }
1302
1303 } // namespace tegra
1304
1305 #endif
1306
1307 /* End of file. */
1308