Home | History | Annotate | Download | only in src
      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 // Third party copyrights are property of their respective owners.
     16 //
     17 // Redistribution and use in source and binary forms, with or without modification,
     18 // are permitted provided that the following conditions are met:
     19 //
     20 //   * Redistribution's of source code must retain the above copyright notice,
     21 //     this list of conditions and the following disclaimer.
     22 //
     23 //   * Redistribution's in binary form must reproduce the above copyright notice,
     24 //     this list of conditions and the following disclaimer in the documentation
     25 //     and/or other materials provided with the distribution.
     26 //
     27 //   * The name of the copyright holders may not be used to endorse or promote products
     28 //     derived from this software without specific prior written permission.
     29 //
     30 // This software is provided by the copyright holders and contributors "as is" and
     31 // any express or implied warranties, including, but not limited to, the implied
     32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     33 // In no event shall the Intel Corporation or contributors be liable for any direct,
     34 // indirect, incidental, special, exemplary, or consequential damages
     35 // (including, but not limited to, procurement of substitute goods or services;
     36 // loss of use, data, or profits; or business interruption) however caused
     37 // and on any theory of liability, whether in contract, strict liability,
     38 // or tort (including negligence or otherwise) arising in any way out of
     39 // the use of this software, even if advised of the possibility of such damage.
     40 //
     41 //M*/
     42 
     43 #include "precomp.hpp"
     44 
     45 //==============================================================================
     46 //
     47 // Error handling helpers
     48 //
     49 //==============================================================================
     50 
     51 namespace
     52 {
     53     #define error_entry(entry)  { entry, #entry }
     54 
     55     struct ErrorEntry
     56     {
     57         int code;
     58         const char* str;
     59     };
     60 
     61     struct ErrorEntryComparer
     62     {
     63         int code;
     64         ErrorEntryComparer(int code_) : code(code_) {}
     65         bool operator()(const ErrorEntry& e) const { return e.code == code; }
     66     };
     67 
     68     //////////////////////////////////////////////////////////////////////////
     69     // NCV errors
     70 
     71     const ErrorEntry ncv_errors [] =
     72     {
     73         error_entry( NCV_SUCCESS ),
     74         error_entry( NCV_UNKNOWN_ERROR ),
     75         error_entry( NCV_CUDA_ERROR ),
     76         error_entry( NCV_NPP_ERROR ),
     77         error_entry( NCV_FILE_ERROR ),
     78         error_entry( NCV_NULL_PTR ),
     79         error_entry( NCV_INCONSISTENT_INPUT ),
     80         error_entry( NCV_TEXTURE_BIND_ERROR ),
     81         error_entry( NCV_DIMENSIONS_INVALID ),
     82         error_entry( NCV_INVALID_ROI ),
     83         error_entry( NCV_INVALID_STEP ),
     84         error_entry( NCV_INVALID_SCALE ),
     85         error_entry( NCV_INVALID_SCALE ),
     86         error_entry( NCV_ALLOCATOR_NOT_INITIALIZED ),
     87         error_entry( NCV_ALLOCATOR_BAD_ALLOC ),
     88         error_entry( NCV_ALLOCATOR_BAD_DEALLOC ),
     89         error_entry( NCV_ALLOCATOR_INSUFFICIENT_CAPACITY ),
     90         error_entry( NCV_ALLOCATOR_DEALLOC_ORDER ),
     91         error_entry( NCV_ALLOCATOR_BAD_REUSE ),
     92         error_entry( NCV_MEM_COPY_ERROR ),
     93         error_entry( NCV_MEM_RESIDENCE_ERROR ),
     94         error_entry( NCV_MEM_INSUFFICIENT_CAPACITY ),
     95         error_entry( NCV_HAAR_INVALID_PIXEL_STEP ),
     96         error_entry( NCV_HAAR_TOO_MANY_FEATURES_IN_CLASSIFIER ),
     97         error_entry( NCV_HAAR_TOO_MANY_FEATURES_IN_CASCADE ),
     98         error_entry( NCV_HAAR_TOO_LARGE_FEATURES ),
     99         error_entry( NCV_HAAR_XML_LOADING_EXCEPTION ),
    100         error_entry( NCV_NOIMPL_HAAR_TILTED_FEATURES ),
    101         error_entry( NCV_WARNING_HAAR_DETECTIONS_VECTOR_OVERFLOW ),
    102         error_entry( NPPST_SUCCESS ),
    103         error_entry( NPPST_ERROR ),
    104         error_entry( NPPST_CUDA_KERNEL_EXECUTION_ERROR ),
    105         error_entry( NPPST_NULL_POINTER_ERROR ),
    106         error_entry( NPPST_TEXTURE_BIND_ERROR ),
    107         error_entry( NPPST_MEMCPY_ERROR ),
    108         error_entry( NPPST_MEM_ALLOC_ERR ),
    109         error_entry( NPPST_MEMFREE_ERR ),
    110         error_entry( NPPST_INVALID_ROI ),
    111         error_entry( NPPST_INVALID_STEP ),
    112         error_entry( NPPST_INVALID_SCALE ),
    113         error_entry( NPPST_MEM_INSUFFICIENT_BUFFER ),
    114         error_entry( NPPST_MEM_RESIDENCE_ERROR ),
    115         error_entry( NPPST_MEM_INTERNAL_ERROR )
    116     };
    117 
    118     const size_t ncv_error_num = sizeof(ncv_errors) / sizeof(ncv_errors[0]);
    119 }
    120 
    121 cv::String cv::cuda::getNcvErrorMessage(int code)
    122 {
    123     size_t idx = std::find_if(ncv_errors, ncv_errors + ncv_error_num, ErrorEntryComparer(code)) - ncv_errors;
    124 
    125     const char* msg = (idx != ncv_error_num) ? ncv_errors[idx].str : "Unknown error code";
    126     String str = cv::format("%s [Code = %d]", msg, code);
    127 
    128     return str;
    129 }
    130 
    131 
    132 static void stdDebugOutput(const cv::String &msg)
    133 {
    134     std::cout << msg.c_str() << std::endl;
    135 }
    136 
    137 
    138 static NCVDebugOutputHandler *debugOutputHandler = stdDebugOutput;
    139 
    140 
    141 void ncvDebugOutput(const cv::String &msg)
    142 {
    143     debugOutputHandler(msg);
    144 }
    145 
    146 
    147 void ncvSetDebugOutputHandler(NCVDebugOutputHandler *func)
    148 {
    149     debugOutputHandler = func;
    150 }
    151 
    152 
    153 //==============================================================================
    154 //
    155 // Memory wrappers and helpers
    156 //
    157 //==============================================================================
    158 
    159 
    160 Ncv32u alignUp(Ncv32u what, Ncv32u alignment)
    161 {
    162     Ncv32u alignMask = alignment-1;
    163     Ncv32u inverseAlignMask = ~alignMask;
    164     Ncv32u res = (what + alignMask) & inverseAlignMask;
    165     return res;
    166 }
    167 
    168 
    169 void NCVMemPtr::clear()
    170 {
    171     ptr = NULL;
    172     memtype = NCVMemoryTypeNone;
    173 }
    174 
    175 
    176 void NCVMemSegment::clear()
    177 {
    178     begin.clear();
    179     size = 0;
    180 }
    181 
    182 
    183 NCVStatus memSegCopyHelper(void *dst, NCVMemoryType dstType, const void *src, NCVMemoryType srcType, size_t sz, cudaStream_t cuStream)
    184 {
    185     NCVStatus ncvStat;
    186     switch (dstType)
    187     {
    188     case NCVMemoryTypeHostPageable:
    189     case NCVMemoryTypeHostPinned:
    190         switch (srcType)
    191         {
    192         case NCVMemoryTypeHostPageable:
    193         case NCVMemoryTypeHostPinned:
    194             memcpy(dst, src, sz);
    195             ncvStat = NCV_SUCCESS;
    196             break;
    197         case NCVMemoryTypeDevice:
    198             if (cuStream != 0)
    199             {
    200                 ncvAssertCUDAReturn(cudaMemcpyAsync(dst, src, sz, cudaMemcpyDeviceToHost, cuStream), NCV_CUDA_ERROR);
    201             }
    202             else
    203             {
    204                 ncvAssertCUDAReturn(cudaMemcpy(dst, src, sz, cudaMemcpyDeviceToHost), NCV_CUDA_ERROR);
    205             }
    206             ncvStat = NCV_SUCCESS;
    207             break;
    208         default:
    209             ncvStat = NCV_MEM_RESIDENCE_ERROR;
    210         }
    211         break;
    212     case NCVMemoryTypeDevice:
    213         switch (srcType)
    214         {
    215         case NCVMemoryTypeHostPageable:
    216         case NCVMemoryTypeHostPinned:
    217             if (cuStream != 0)
    218             {
    219                 ncvAssertCUDAReturn(cudaMemcpyAsync(dst, src, sz, cudaMemcpyHostToDevice, cuStream), NCV_CUDA_ERROR);
    220             }
    221             else
    222             {
    223                 ncvAssertCUDAReturn(cudaMemcpy(dst, src, sz, cudaMemcpyHostToDevice), NCV_CUDA_ERROR);
    224             }
    225             ncvStat = NCV_SUCCESS;
    226             break;
    227         case NCVMemoryTypeDevice:
    228             if (cuStream != 0)
    229             {
    230                 ncvAssertCUDAReturn(cudaMemcpyAsync(dst, src, sz, cudaMemcpyDeviceToDevice, cuStream), NCV_CUDA_ERROR);
    231             }
    232             else
    233             {
    234                 ncvAssertCUDAReturn(cudaMemcpy(dst, src, sz, cudaMemcpyDeviceToDevice), NCV_CUDA_ERROR);
    235             }
    236             ncvStat = NCV_SUCCESS;
    237             break;
    238         default:
    239             ncvStat = NCV_MEM_RESIDENCE_ERROR;
    240         }
    241         break;
    242     default:
    243         ncvStat = NCV_MEM_RESIDENCE_ERROR;
    244     }
    245 
    246     return ncvStat;
    247 }
    248 
    249 
    250 NCVStatus memSegCopyHelper2D(void *dst, Ncv32u dstPitch, NCVMemoryType dstType,
    251                              const void *src, Ncv32u srcPitch, NCVMemoryType srcType,
    252                              Ncv32u widthbytes, Ncv32u height, cudaStream_t cuStream)
    253 {
    254     NCVStatus ncvStat;
    255     switch (dstType)
    256     {
    257     case NCVMemoryTypeHostPageable:
    258     case NCVMemoryTypeHostPinned:
    259         switch (srcType)
    260         {
    261         case NCVMemoryTypeHostPageable:
    262         case NCVMemoryTypeHostPinned:
    263             for (Ncv32u i=0; i<height; i++)
    264             {
    265                 memcpy((char*)dst + i * dstPitch, (char*)src + i * srcPitch, widthbytes);
    266             }
    267             ncvStat = NCV_SUCCESS;
    268             break;
    269         case NCVMemoryTypeDevice:
    270             if (cuStream != 0)
    271             {
    272                 ncvAssertCUDAReturn(cudaMemcpy2DAsync(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyDeviceToHost, cuStream), NCV_CUDA_ERROR);
    273             }
    274             else
    275             {
    276                 ncvAssertCUDAReturn(cudaMemcpy2D(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyDeviceToHost), NCV_CUDA_ERROR);
    277             }
    278             ncvStat = NCV_SUCCESS;
    279             break;
    280         default:
    281             ncvStat = NCV_MEM_RESIDENCE_ERROR;
    282         }
    283         break;
    284     case NCVMemoryTypeDevice:
    285         switch (srcType)
    286         {
    287         case NCVMemoryTypeHostPageable:
    288         case NCVMemoryTypeHostPinned:
    289             if (cuStream != 0)
    290             {
    291                 ncvAssertCUDAReturn(cudaMemcpy2DAsync(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyHostToDevice, cuStream), NCV_CUDA_ERROR);
    292             }
    293             else
    294             {
    295                 ncvAssertCUDAReturn(cudaMemcpy2D(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyHostToDevice), NCV_CUDA_ERROR);
    296             }
    297             ncvStat = NCV_SUCCESS;
    298             break;
    299         case NCVMemoryTypeDevice:
    300             if (cuStream != 0)
    301             {
    302                 ncvAssertCUDAReturn(cudaMemcpy2DAsync(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyDeviceToDevice, cuStream), NCV_CUDA_ERROR);
    303             }
    304             else
    305             {
    306                 ncvAssertCUDAReturn(cudaMemcpy2D(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyDeviceToDevice), NCV_CUDA_ERROR);
    307             }
    308             ncvStat = NCV_SUCCESS;
    309             break;
    310         default:
    311             ncvStat = NCV_MEM_RESIDENCE_ERROR;
    312         }
    313         break;
    314     default:
    315         ncvStat = NCV_MEM_RESIDENCE_ERROR;
    316     }
    317 
    318     return ncvStat;
    319 }
    320 
    321 
    322 //===================================================================
    323 //
    324 // NCVMemStackAllocator class members implementation
    325 //
    326 //===================================================================
    327 
    328 
    329 NCVMemStackAllocator::NCVMemStackAllocator(Ncv32u alignment_) :
    330     _memType(NCVMemoryTypeNone),
    331     _alignment(alignment_),
    332     allocBegin(NULL),
    333     begin(NULL),
    334     end(NULL),
    335     currentSize(0),
    336     _maxSize(0),
    337     bReusesMemory(false)
    338 {
    339     NcvBool bProperAlignment = (alignment_ & (alignment_ - 1)) == 0;
    340     ncvAssertPrintCheck(bProperAlignment, "NCVMemStackAllocator ctor:: alignment not power of 2");
    341 }
    342 
    343 
    344 NCVMemStackAllocator::NCVMemStackAllocator(NCVMemoryType memT, size_t capacity, Ncv32u alignment_, void *reusePtr) :
    345     _memType(memT),
    346     _alignment(alignment_),
    347     allocBegin(NULL),
    348     currentSize(0),
    349     _maxSize(0)
    350 {
    351     NcvBool bProperAlignment = (alignment_ & (alignment_ - 1)) == 0;
    352     ncvAssertPrintCheck(bProperAlignment, "NCVMemStackAllocator ctor:: _alignment not power of 2");
    353     ncvAssertPrintCheck(memT != NCVMemoryTypeNone, "NCVMemStackAllocator ctor:: Incorrect allocator type");
    354 
    355     allocBegin = NULL;
    356 
    357     if (reusePtr == NULL && capacity != 0)
    358     {
    359         bReusesMemory = false;
    360         switch (memT)
    361         {
    362         case NCVMemoryTypeDevice:
    363             ncvAssertCUDAReturn(cudaMalloc(&allocBegin, capacity), );
    364             break;
    365         case NCVMemoryTypeHostPinned:
    366             ncvAssertCUDAReturn(cudaMallocHost(&allocBegin, capacity), );
    367             break;
    368         case NCVMemoryTypeHostPageable:
    369             allocBegin = (Ncv8u *)malloc(capacity);
    370             break;
    371         default:;
    372         }
    373     }
    374     else
    375     {
    376         bReusesMemory = true;
    377         allocBegin = (Ncv8u *)reusePtr;
    378     }
    379 
    380     if (capacity == 0)
    381     {
    382         allocBegin = (Ncv8u *)(0x1);
    383     }
    384 
    385     if (!isCounting())
    386     {
    387         begin = allocBegin;
    388         end = begin + capacity;
    389     }
    390 }
    391 
    392 
    393 NCVMemStackAllocator::~NCVMemStackAllocator()
    394 {
    395     if (allocBegin != NULL)
    396     {
    397         ncvAssertPrintCheck(currentSize == 0, "NCVMemStackAllocator dtor:: not all objects were deallocated properly, forcing destruction");
    398 
    399         if (!bReusesMemory && (allocBegin != (Ncv8u *)(0x1)))
    400         {
    401             switch (_memType)
    402             {
    403             case NCVMemoryTypeDevice:
    404                 ncvAssertCUDAReturn(cudaFree(allocBegin), );
    405                 break;
    406             case NCVMemoryTypeHostPinned:
    407                 ncvAssertCUDAReturn(cudaFreeHost(allocBegin), );
    408                 break;
    409             case NCVMemoryTypeHostPageable:
    410                 free(allocBegin);
    411                 break;
    412             default:;
    413             }
    414         }
    415 
    416         allocBegin = NULL;
    417     }
    418 }
    419 
    420 
    421 NCVStatus NCVMemStackAllocator::alloc(NCVMemSegment &seg, size_t size)
    422 {
    423     seg.clear();
    424     ncvAssertReturn(isInitialized(), NCV_ALLOCATOR_BAD_ALLOC);
    425 
    426     size = alignUp(static_cast<Ncv32u>(size), this->_alignment);
    427     this->currentSize += size;
    428     this->_maxSize = std::max(this->_maxSize, this->currentSize);
    429 
    430     if (!isCounting())
    431     {
    432         size_t availSize = end - begin;
    433         ncvAssertReturn(size <= availSize, NCV_ALLOCATOR_INSUFFICIENT_CAPACITY);
    434     }
    435 
    436     seg.begin.ptr = begin;
    437     seg.begin.memtype = this->_memType;
    438     seg.size = size;
    439     begin += size;
    440 
    441     return NCV_SUCCESS;
    442 }
    443 
    444 
    445 NCVStatus NCVMemStackAllocator::dealloc(NCVMemSegment &seg)
    446 {
    447     ncvAssertReturn(isInitialized(), NCV_ALLOCATOR_BAD_ALLOC);
    448     ncvAssertReturn(seg.begin.memtype == this->_memType, NCV_ALLOCATOR_BAD_DEALLOC);
    449     ncvAssertReturn(seg.begin.ptr != NULL || isCounting(), NCV_ALLOCATOR_BAD_DEALLOC);
    450     ncvAssertReturn(seg.begin.ptr == begin - seg.size, NCV_ALLOCATOR_DEALLOC_ORDER);
    451 
    452     currentSize -= seg.size;
    453     begin -= seg.size;
    454 
    455     seg.clear();
    456 
    457     ncvAssertReturn(allocBegin <= begin, NCV_ALLOCATOR_BAD_DEALLOC);
    458 
    459     return NCV_SUCCESS;
    460 }
    461 
    462 
    463 NcvBool NCVMemStackAllocator::isInitialized(void) const
    464 {
    465     return (((this->_alignment & (this->_alignment-1)) == 0) && isCounting()) || this->allocBegin != NULL;
    466 }
    467 
    468 
    469 NcvBool NCVMemStackAllocator::isCounting(void) const
    470 {
    471     return this->_memType == NCVMemoryTypeNone;
    472 }
    473 
    474 
    475 NCVMemoryType NCVMemStackAllocator::memType(void) const
    476 {
    477     return this->_memType;
    478 }
    479 
    480 
    481 Ncv32u NCVMemStackAllocator::alignment(void) const
    482 {
    483     return this->_alignment;
    484 }
    485 
    486 
    487 size_t NCVMemStackAllocator::maxSize(void) const
    488 {
    489     return this->_maxSize;
    490 }
    491 
    492 
    493 //===================================================================
    494 //
    495 // NCVMemNativeAllocator class members implementation
    496 //
    497 //===================================================================
    498 
    499 
    500 NCVMemNativeAllocator::NCVMemNativeAllocator(NCVMemoryType memT, Ncv32u alignment_) :
    501     _memType(memT),
    502     _alignment(alignment_),
    503     currentSize(0),
    504     _maxSize(0)
    505 {
    506     ncvAssertPrintReturn(memT != NCVMemoryTypeNone, "NCVMemNativeAllocator ctor:: counting not permitted for this allocator type", );
    507 }
    508 
    509 
    510 NCVMemNativeAllocator::~NCVMemNativeAllocator()
    511 {
    512     ncvAssertPrintCheck(currentSize == 0, "NCVMemNativeAllocator dtor:: detected memory leak");
    513 }
    514 
    515 
    516 NCVStatus NCVMemNativeAllocator::alloc(NCVMemSegment &seg, size_t size)
    517 {
    518     seg.clear();
    519     ncvAssertReturn(isInitialized(), NCV_ALLOCATOR_BAD_ALLOC);
    520 
    521     switch (this->_memType)
    522     {
    523     case NCVMemoryTypeDevice:
    524         ncvAssertCUDAReturn(cudaMalloc(&seg.begin.ptr, size), NCV_CUDA_ERROR);
    525         break;
    526     case NCVMemoryTypeHostPinned:
    527         ncvAssertCUDAReturn(cudaMallocHost(&seg.begin.ptr, size), NCV_CUDA_ERROR);
    528         break;
    529     case NCVMemoryTypeHostPageable:
    530         seg.begin.ptr = (Ncv8u *)malloc(size);
    531         break;
    532     default:;
    533     }
    534 
    535     this->currentSize += alignUp(static_cast<Ncv32u>(size), this->_alignment);
    536     this->_maxSize = std::max(this->_maxSize, this->currentSize);
    537 
    538     seg.begin.memtype = this->_memType;
    539     seg.size = size;
    540 
    541     return NCV_SUCCESS;
    542 }
    543 
    544 
    545 NCVStatus NCVMemNativeAllocator::dealloc(NCVMemSegment &seg)
    546 {
    547     ncvAssertReturn(isInitialized(), NCV_ALLOCATOR_BAD_ALLOC);
    548     ncvAssertReturn(seg.begin.memtype == this->_memType, NCV_ALLOCATOR_BAD_DEALLOC);
    549     ncvAssertReturn(seg.begin.ptr != NULL, NCV_ALLOCATOR_BAD_DEALLOC);
    550 
    551     ncvAssertReturn(currentSize >= alignUp(static_cast<Ncv32u>(seg.size), this->_alignment), NCV_ALLOCATOR_BAD_DEALLOC);
    552     currentSize -= alignUp(static_cast<Ncv32u>(seg.size), this->_alignment);
    553 
    554     switch (this->_memType)
    555     {
    556     case NCVMemoryTypeDevice:
    557         ncvAssertCUDAReturn(cudaFree(seg.begin.ptr), NCV_CUDA_ERROR);
    558         break;
    559     case NCVMemoryTypeHostPinned:
    560         ncvAssertCUDAReturn(cudaFreeHost(seg.begin.ptr), NCV_CUDA_ERROR);
    561         break;
    562     case NCVMemoryTypeHostPageable:
    563         free(seg.begin.ptr);
    564         break;
    565     default:;
    566     }
    567 
    568     seg.clear();
    569 
    570     return NCV_SUCCESS;
    571 }
    572 
    573 
    574 NcvBool NCVMemNativeAllocator::isInitialized(void) const
    575 {
    576     return (this->_alignment != 0);
    577 }
    578 
    579 
    580 NcvBool NCVMemNativeAllocator::isCounting(void) const
    581 {
    582     return false;
    583 }
    584 
    585 
    586 NCVMemoryType NCVMemNativeAllocator::memType(void) const
    587 {
    588     return this->_memType;
    589 }
    590 
    591 
    592 Ncv32u NCVMemNativeAllocator::alignment(void) const
    593 {
    594     return this->_alignment;
    595 }
    596 
    597 
    598 size_t NCVMemNativeAllocator::maxSize(void) const
    599 {
    600     return this->_maxSize;
    601 }
    602 
    603 
    604 //===================================================================
    605 //
    606 // Time and timer routines
    607 //
    608 //===================================================================
    609 
    610 
    611 typedef struct _NcvTimeMoment NcvTimeMoment;
    612 
    613 #if defined(_WIN32) || defined(_WIN64)
    614 
    615     #include <Windows.h>
    616 
    617     typedef struct _NcvTimeMoment
    618     {
    619         LONGLONG moment, freq;
    620     } NcvTimeMoment;
    621 
    622 
    623     static void _ncvQueryMoment(NcvTimeMoment *t)
    624     {
    625         QueryPerformanceFrequency((LARGE_INTEGER *)&(t->freq));
    626         QueryPerformanceCounter((LARGE_INTEGER *)&(t->moment));
    627     }
    628 
    629 
    630     double _ncvMomentToMicroseconds(NcvTimeMoment *t)
    631     {
    632         return 1000000.0 * t->moment / t->freq;
    633     }
    634 
    635 
    636     double _ncvMomentsDiffToMicroseconds(NcvTimeMoment *t1, NcvTimeMoment *t2)
    637     {
    638         return 1000000.0 * 2 * ((t2->moment) - (t1->moment)) / (t1->freq + t2->freq);
    639     }
    640 
    641 
    642     double _ncvMomentsDiffToMilliseconds(NcvTimeMoment *t1, NcvTimeMoment *t2)
    643     {
    644         return 1000.0 * 2 * ((t2->moment) - (t1->moment)) / (t1->freq + t2->freq);
    645     }
    646 
    647 #elif defined(__GNUC__)
    648 
    649     #include <sys/time.h>
    650 
    651     typedef struct _NcvTimeMoment
    652     {
    653         struct timeval tv;
    654         struct timezone tz;
    655     } NcvTimeMoment;
    656 
    657 
    658     void _ncvQueryMoment(NcvTimeMoment *t)
    659     {
    660         gettimeofday(& t->tv, & t->tz);
    661     }
    662 
    663 
    664     double _ncvMomentToMicroseconds(NcvTimeMoment *t)
    665     {
    666         return 1000000.0 * t->tv.tv_sec + (double)t->tv.tv_usec;
    667     }
    668 
    669 
    670     double _ncvMomentsDiffToMicroseconds(NcvTimeMoment *t1, NcvTimeMoment *t2)
    671     {
    672         return (((double)t2->tv.tv_sec - (double)t1->tv.tv_sec) * 1000000 + (double)t2->tv.tv_usec - (double)t1->tv.tv_usec);
    673     }
    674 
    675     double _ncvMomentsDiffToMilliseconds(NcvTimeMoment *t1, NcvTimeMoment *t2)
    676     {
    677         return ((double)t2->tv.tv_sec - (double)t1->tv.tv_sec) * 1000;
    678     }
    679 
    680 #endif //#if defined(_WIN32) || defined(_WIN64)
    681 
    682 
    683 struct _NcvTimer
    684 {
    685     NcvTimeMoment t1, t2;
    686 };
    687 
    688 
    689 NcvTimer ncvStartTimer(void)
    690 {
    691     struct _NcvTimer *t;
    692     t = (struct _NcvTimer *)malloc(sizeof(struct _NcvTimer));
    693     _ncvQueryMoment(&t->t1);
    694     return t;
    695 }
    696 
    697 
    698 double ncvEndQueryTimerUs(NcvTimer t)
    699 {
    700     double res;
    701     _ncvQueryMoment(&t->t2);
    702     res = _ncvMomentsDiffToMicroseconds(&t->t1, &t->t2);
    703     free(t);
    704     return res;
    705 }
    706 
    707 
    708 double ncvEndQueryTimerMs(NcvTimer t)
    709 {
    710     double res;
    711     _ncvQueryMoment(&t->t2);
    712     res = _ncvMomentsDiffToMilliseconds(&t->t1, &t->t2);
    713     free(t);
    714     return res;
    715 }
    716 
    717 
    718 //===================================================================
    719 //
    720 // Operations with rectangles
    721 //
    722 //===================================================================
    723 
    724 struct RectConvert
    725 {
    726     cv::Rect operator()(const NcvRect32u& nr) const { return cv::Rect(nr.x, nr.y, nr.width, nr.height); }
    727     NcvRect32u operator()(const cv::Rect& nr) const
    728     {
    729         NcvRect32u rect;
    730         rect.x = nr.x;
    731         rect.y = nr.y;
    732         rect.width = nr.width;
    733         rect.height = nr.height;
    734         return rect;
    735     }
    736 };
    737 
    738 static void groupRectangles(std::vector<NcvRect32u> &hypotheses, int groupThreshold, double eps, std::vector<Ncv32u> *weights)
    739 {
    740 #ifndef HAVE_OPENCV_OBJDETECT
    741     (void) hypotheses;
    742     (void) groupThreshold;
    743     (void) eps;
    744     (void) weights;
    745     CV_Error(cv::Error::StsNotImplemented, "This functionality requires objdetect module");
    746 #else
    747     std::vector<cv::Rect> rects(hypotheses.size());
    748     std::transform(hypotheses.begin(), hypotheses.end(), rects.begin(), RectConvert());
    749 
    750     if (weights)
    751     {
    752         std::vector<int> weights_int;
    753         weights_int.assign(weights->begin(), weights->end());
    754         cv::groupRectangles(rects, weights_int, groupThreshold, eps);
    755     }
    756     else
    757     {
    758         cv::groupRectangles(rects, groupThreshold, eps);
    759     }
    760     std::transform(rects.begin(), rects.end(), hypotheses.begin(), RectConvert());
    761     hypotheses.resize(rects.size());
    762 #endif
    763 }
    764 
    765 
    766 
    767 NCVStatus ncvGroupRectangles_host(NCVVector<NcvRect32u> &hypotheses,
    768                                   Ncv32u &numHypotheses,
    769                                   Ncv32u minNeighbors,
    770                                   Ncv32f intersectEps,
    771                                   NCVVector<Ncv32u> *hypothesesWeights)
    772 {
    773     ncvAssertReturn(hypotheses.memType() == NCVMemoryTypeHostPageable ||
    774                     hypotheses.memType() == NCVMemoryTypeHostPinned, NCV_MEM_RESIDENCE_ERROR);
    775     if (hypothesesWeights != NULL)
    776     {
    777         ncvAssertReturn(hypothesesWeights->memType() == NCVMemoryTypeHostPageable ||
    778                         hypothesesWeights->memType() == NCVMemoryTypeHostPinned, NCV_MEM_RESIDENCE_ERROR);
    779     }
    780 
    781     if (numHypotheses == 0)
    782     {
    783         return NCV_SUCCESS;
    784     }
    785 
    786     std::vector<NcvRect32u> rects(numHypotheses);
    787     memcpy(&rects[0], hypotheses.ptr(), numHypotheses * sizeof(NcvRect32u));
    788 
    789     std::vector<Ncv32u> weights;
    790     if (hypothesesWeights != NULL)
    791     {
    792         groupRectangles(rects, minNeighbors, intersectEps, &weights);
    793     }
    794     else
    795     {
    796         groupRectangles(rects, minNeighbors, intersectEps, NULL);
    797     }
    798 
    799     numHypotheses = (Ncv32u)rects.size();
    800     if (numHypotheses > 0)
    801     {
    802         memcpy(hypotheses.ptr(), &rects[0], numHypotheses * sizeof(NcvRect32u));
    803     }
    804 
    805     if (hypothesesWeights != NULL)
    806     {
    807         memcpy(hypothesesWeights->ptr(), &weights[0], numHypotheses * sizeof(Ncv32u));
    808     }
    809 
    810     return NCV_SUCCESS;
    811 }
    812 
    813 
    814 template <class T>
    815 static NCVStatus drawRectsWrapperHost(T *h_dst,
    816                                       Ncv32u dstStride,
    817                                       Ncv32u dstWidth,
    818                                       Ncv32u dstHeight,
    819                                       NcvRect32u *h_rects,
    820                                       Ncv32u numRects,
    821                                       T color)
    822 {
    823     ncvAssertReturn(h_dst != NULL && h_rects != NULL, NCV_NULL_PTR);
    824     ncvAssertReturn(dstWidth > 0 && dstHeight > 0, NCV_DIMENSIONS_INVALID);
    825     ncvAssertReturn(dstStride >= dstWidth, NCV_INVALID_STEP);
    826     ncvAssertReturn(numRects != 0, NCV_SUCCESS);
    827     ncvAssertReturn(numRects <= dstWidth * dstHeight, NCV_DIMENSIONS_INVALID);
    828 
    829     for (Ncv32u i=0; i<numRects; i++)
    830     {
    831         NcvRect32u rect = h_rects[i];
    832 
    833         if (rect.x < dstWidth)
    834         {
    835             for (Ncv32u each=rect.y; each<rect.y+rect.height && each<dstHeight; each++)
    836             {
    837                 h_dst[each*dstStride+rect.x] = color;
    838             }
    839         }
    840         if (rect.x+rect.width-1 < dstWidth)
    841         {
    842             for (Ncv32u each=rect.y; each<rect.y+rect.height && each<dstHeight; each++)
    843             {
    844                 h_dst[each*dstStride+rect.x+rect.width-1] = color;
    845             }
    846         }
    847         if (rect.y < dstHeight)
    848         {
    849             for (Ncv32u j=rect.x; j<rect.x+rect.width && j<dstWidth; j++)
    850             {
    851                 h_dst[rect.y*dstStride+j] = color;
    852             }
    853         }
    854         if (rect.y + rect.height - 1 < dstHeight)
    855         {
    856             for (Ncv32u j=rect.x; j<rect.x+rect.width && j<dstWidth; j++)
    857             {
    858                 h_dst[(rect.y+rect.height-1)*dstStride+j] = color;
    859             }
    860         }
    861     }
    862 
    863     return NCV_SUCCESS;
    864 }
    865 
    866 
    867 NCVStatus ncvDrawRects_8u_host(Ncv8u *h_dst,
    868                                Ncv32u dstStride,
    869                                Ncv32u dstWidth,
    870                                Ncv32u dstHeight,
    871                                NcvRect32u *h_rects,
    872                                Ncv32u numRects,
    873                                Ncv8u color)
    874 {
    875     return drawRectsWrapperHost(h_dst, dstStride, dstWidth, dstHeight, h_rects, numRects, color);
    876 }
    877 
    878 
    879 NCVStatus ncvDrawRects_32u_host(Ncv32u *h_dst,
    880                                 Ncv32u dstStride,
    881                                 Ncv32u dstWidth,
    882                                 Ncv32u dstHeight,
    883                                 NcvRect32u *h_rects,
    884                                 Ncv32u numRects,
    885                                 Ncv32u color)
    886 {
    887     return drawRectsWrapperHost(h_dst, dstStride, dstWidth, dstHeight, h_rects, numRects, color);
    888 }
    889