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
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    }
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
119std::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
151std::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
197namespace cv
198{
199
200Exception::Exception() { code = 0; line = 0; }
201
202Exception::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
208Exception::~Exception() throw() {}
209
210/*!
211 \return the error description and the context as a text string.
212 */
213const char* Exception::what() const throw() { return msg.c_str(); }
214
215void 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
223struct HWFeatures
224{
225    enum { MAX_FEATURE = CV_HARDWARE_MAX_FEATURE };
226
227    HWFeatures(void)
228    {
229        memset( have, 0, sizeof(have) );
230        x86_family = 0;
231    }
232
233    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
355static HWFeatures  featuresEnabled = HWFeatures::initialize(), featuresDisabled = HWFeatures();
356static HWFeatures* currentFeatures = &featuresEnabled;
357
358bool checkHardwareSupport(int feature)
359{
360    CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
361    return currentFeatures->have[feature];
362}
363
364
365volatile bool useOptimizedFlag = true;
366#ifdef HAVE_IPP
367struct IPPInitializer
368{
369    IPPInitializer(void)
370    {
371#if IPP_VERSION_MAJOR >= 8
372        ippInit();
373#else
374        ippStaticInit();
375#endif
376    }
377};
378
379IPPInitializer ippInitializer;
380#endif
381
382volatile bool USE_SSE2 = featuresEnabled.have[CV_CPU_SSE2];
383volatile bool USE_SSE4_2 = featuresEnabled.have[CV_CPU_SSE4_2];
384volatile bool USE_AVX = featuresEnabled.have[CV_CPU_AVX];
385volatile bool USE_AVX2 = featuresEnabled.have[CV_CPU_AVX2];
386
387void 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
400bool useOptimized(void)
401{
402    return useOptimizedFlag;
403}
404
405int64 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
425double 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
450int64 getCPUTickCount(void)
451{
452    int64 x;
453    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
454    return x;
455}
456#elif defined(__x86_64__)
457
458int64 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
467int64 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
491int64 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
505int64 getCPUTickCount(void)
506{
507    return getTickCount();
508}
509//#endif
510
511#endif
512
513const String& getBuildInformation()
514{
515    static String build_info =
516#include "version_string.inc"
517    ;
518    return build_info;
519}
520
521String 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
542String 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
618static CvErrorCallback customErrorCallback = 0;
619static void* customErrorCallbackData = 0;
620static bool breakOnError = false;
621
622bool setBreakOnError(bool value)
623{
624    bool prevVal = breakOnError;
625    breakOnError = value;
626    return prevVal;
627}
628
629void 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
658void 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
663CvErrorCallback
664redirectError( 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
679CV_IMPL int cvCheckHardwareSupport(int feature)
680{
681    CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
682    return cv::currentFeatures->have[feature];
683}
684
685CV_IMPL int cvUseOptimized( int flag )
686{
687    int prevMode = cv::useOptimizedFlag;
688    cv::setUseOptimized( flag != 0 );
689    return prevMode;
690}
691
692CV_IMPL int64  cvGetTickCount(void)
693{
694    return cv::getTickCount();
695}
696
697CV_IMPL double cvGetTickFrequency(void)
698{
699    return cv::getTickFrequency()*1e-6;
700}
701
702CV_IMPL CvErrorCallback
703cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
704{
705    return cv::redirectError(errCallback, userdata, prevUserdata);
706}
707
708CV_IMPL int cvNulDevReport( int, const char*, const char*,
709                            const char*, int, void* )
710{
711    return 0;
712}
713
714CV_IMPL int cvStdErrReport( int, const char*, const char*,
715                            const char*, int, void* )
716{
717    return 0;
718}
719
720CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
721                            const char*, int, void* )
722{
723    return 0;
724}
725
726CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
727{
728    return 0;
729}
730
731
732CV_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
776CV_IMPL int cvGetErrMode(void)
777{
778    return 0;
779}
780
781CV_IMPL int cvSetErrMode(int)
782{
783    return 0;
784}
785
786CV_IMPL int cvGetErrStatus(void)
787{
788    return 0;
789}
790
791CV_IMPL void cvSetErrStatus(int)
792{
793}
794
795
796CV_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 */
804CV_IMPL int
805cvErrorFromIppStatus( 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
835namespace cv {
836bool __termination = false;
837}
838
839namespace cv
840{
841
842#if defined WIN32 || defined _WIN32 || defined WINCE
843
844struct Mutex::Impl
845{
846    Impl()
847    {
848#if (_WIN32_WINNT >= 0x0600)
849        ::InitializeCriticalSectionEx(&cs, 1000, 0);
850#else
851        ::InitializeCriticalSection(&cs);
852#endif
853        refcount = 1;
854    }
855    ~Impl() { DeleteCriticalSection(&cs); }
856
857    void lock() { EnterCriticalSection(&cs); }
858    bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
859    void unlock() { LeaveCriticalSection(&cs); }
860
861    CRITICAL_SECTION cs;
862    int refcount;
863};
864
865#else
866
867struct 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
891Mutex::Mutex()
892{
893    impl = new Mutex::Impl;
894}
895
896Mutex::~Mutex()
897{
898    if( CV_XADD(&impl->refcount, -1) == 1 )
899        delete impl;
900    impl = 0;
901}
902
903Mutex::Mutex(const Mutex& m)
904{
905    impl = m.impl;
906    CV_XADD(&impl->refcount, 1);
907}
908
909Mutex& 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
918void Mutex::lock() { impl->lock(); }
919void Mutex::unlock() { impl->unlock(); }
920bool Mutex::trylock() { return impl->trylock(); }
921
922
923//////////////////////////////// thread-local storage ////////////////////////////////
924
925class TLSStorage
926{
927    std::vector<void*> tlsData_;
928public:
929    TLSStorage() { tlsData_.reserve(16); }
930    ~TLSStorage();
931    inline void* getData(int key) const
932    {
933        CV_DbgAssert(key >= 0);
934        return (key < (int)tlsData_.size()) ? tlsData_[key] : NULL;
935    }
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
958    static void deleteThreadData()
959    {
960        if (g_tlsdata)
961        {
962            delete g_tlsdata;
963            g_tlsdata = NULL;
964        }
965    }
966
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
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
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
1012extern "C"
1013BOOL 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
1037    static void deleteTLSStorage(void* data)
1038    {
1039        delete (TLSStorage*)data;
1040    }
1041
1042    static void makeKey()
1043    {
1044        int errcode = pthread_key_create(&tlsKey, deleteTLSStorage);
1045        CV_Assert(errcode == 0);
1046    }
1047
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
1061class TLSContainerStorage
1062{
1063    cv::Mutex mutex_;
1064    std::vector<TLSDataContainer*> tlsContainers_;
1065public:
1066    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
1076    int allocateKey(TLSDataContainer* pContainer)
1077    {
1078        cv::AutoLock lock(mutex_);
1079        tlsContainers_.push_back(pContainer);
1080        return (int)tlsContainers_.size() - 1;
1081    }
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
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
1109static TLSContainerStorage& getTLSContainerStorage()
1110{
1111    static TLSContainerStorage *tlsContainerStorage = new TLSContainerStorage();
1112    return *tlsContainerStorage;
1113}
1114
1115TLSDataContainer::TLSDataContainer()
1116    : key_(-1)
1117{
1118    key_ = getTLSContainerStorage().allocateKey(this);
1119}
1120
1121TLSDataContainer::~TLSDataContainer()
1122{
1123    getTLSContainerStorage().releaseKey(key_, this);
1124    key_ = -1;
1125}
1126
1127void* 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
1141TLSStorage::~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
1157TLSData<CoreTLSData>& getCoreTlsData()
1158{
1159    static TLSData<CoreTLSData> *value = new TLSData<CoreTLSData>();
1160    return *value;
1161}
1162
1163
1164
1165#ifdef CV_COLLECT_IMPL_DATA
1166ImplCollector& getImplData()
1167{
1168    static ImplCollector *value = new ImplCollector();
1169    return *value;
1170}
1171
1172void 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
1181void 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
1197int 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
1206bool useCollection()
1207{
1208    return getImplData().useCollection;
1209}
1210
1211void setUseCollection(bool flag)
1212{
1213    cv::AutoLock lock(getImplData().mutex);
1214
1215    getImplData().useCollection = flag;
1216}
1217#endif
1218
1219namespace ipp
1220{
1221
1222static int ippStatus = 0; // 0 - all is ok, -1 - IPP functions failed
1223static const char * funcname = NULL, * filename = NULL;
1224static int linen = 0;
1225
1226void 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
1234int getIppStatus()
1235{
1236    return ippStatus;
1237}
1238
1239String getIppErrorLocation()
1240{
1241    return format("%s:%d %s", filename ? filename : "", linen, funcname ? funcname : "");
1242}
1243
1244bool 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
1262void 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
1279namespace tegra {
1280
1281bool 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
1297void 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