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;
ErrorEntryComparer__anon7f9beb760111::ErrorEntryComparer64         ErrorEntryComparer(int code_) : code(code_) {}
operator ()__anon7f9beb760111::ErrorEntryComparer65         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 
getNcvErrorMessage(int code)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 
stdDebugOutput(const cv::String & msg)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 
ncvDebugOutput(const cv::String & msg)141 void ncvDebugOutput(const cv::String &msg)
142 {
143     debugOutputHandler(msg);
144 }
145 
146 
ncvSetDebugOutputHandler(NCVDebugOutputHandler * func)147 void ncvSetDebugOutputHandler(NCVDebugOutputHandler *func)
148 {
149     debugOutputHandler = func;
150 }
151 
152 
153 //==============================================================================
154 //
155 // Memory wrappers and helpers
156 //
157 //==============================================================================
158 
159 
alignUp(Ncv32u what,Ncv32u alignment)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 
clear()169 void NCVMemPtr::clear()
170 {
171     ptr = NULL;
172     memtype = NCVMemoryTypeNone;
173 }
174 
175 
clear()176 void NCVMemSegment::clear()
177 {
178     begin.clear();
179     size = 0;
180 }
181 
182 
memSegCopyHelper(void * dst,NCVMemoryType dstType,const void * src,NCVMemoryType srcType,size_t sz,cudaStream_t cuStream)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 
memSegCopyHelper2D(void * dst,Ncv32u dstPitch,NCVMemoryType dstType,const void * src,Ncv32u srcPitch,NCVMemoryType srcType,Ncv32u widthbytes,Ncv32u height,cudaStream_t cuStream)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 
NCVMemStackAllocator(Ncv32u alignment_)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 
NCVMemStackAllocator(NCVMemoryType memT,size_t capacity,Ncv32u alignment_,void * reusePtr)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 
~NCVMemStackAllocator()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 
alloc(NCVMemSegment & seg,size_t size)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 
dealloc(NCVMemSegment & seg)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 
isInitialized(void) const463 NcvBool NCVMemStackAllocator::isInitialized(void) const
464 {
465     return (((this->_alignment & (this->_alignment-1)) == 0) && isCounting()) || this->allocBegin != NULL;
466 }
467 
468 
isCounting(void) const469 NcvBool NCVMemStackAllocator::isCounting(void) const
470 {
471     return this->_memType == NCVMemoryTypeNone;
472 }
473 
474 
memType(void) const475 NCVMemoryType NCVMemStackAllocator::memType(void) const
476 {
477     return this->_memType;
478 }
479 
480 
alignment(void) const481 Ncv32u NCVMemStackAllocator::alignment(void) const
482 {
483     return this->_alignment;
484 }
485 
486 
maxSize(void) const487 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 
NCVMemNativeAllocator(NCVMemoryType memT,Ncv32u alignment_)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 
~NCVMemNativeAllocator()510 NCVMemNativeAllocator::~NCVMemNativeAllocator()
511 {
512     ncvAssertPrintCheck(currentSize == 0, "NCVMemNativeAllocator dtor:: detected memory leak");
513 }
514 
515 
alloc(NCVMemSegment & seg,size_t size)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 
dealloc(NCVMemSegment & seg)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 
isInitialized(void) const574 NcvBool NCVMemNativeAllocator::isInitialized(void) const
575 {
576     return (this->_alignment != 0);
577 }
578 
579 
isCounting(void) const580 NcvBool NCVMemNativeAllocator::isCounting(void) const
581 {
582     return false;
583 }
584 
585 
memType(void) const586 NCVMemoryType NCVMemNativeAllocator::memType(void) const
587 {
588     return this->_memType;
589 }
590 
591 
alignment(void) const592 Ncv32u NCVMemNativeAllocator::alignment(void) const
593 {
594     return this->_alignment;
595 }
596 
597 
maxSize(void) const598 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 
_ncvQueryMoment(NcvTimeMoment * t)623     static void _ncvQueryMoment(NcvTimeMoment *t)
624     {
625         QueryPerformanceFrequency((LARGE_INTEGER *)&(t->freq));
626         QueryPerformanceCounter((LARGE_INTEGER *)&(t->moment));
627     }
628 
629 
_ncvMomentToMicroseconds(NcvTimeMoment * t)630     double _ncvMomentToMicroseconds(NcvTimeMoment *t)
631     {
632         return 1000000.0 * t->moment / t->freq;
633     }
634 
635 
_ncvMomentsDiffToMicroseconds(NcvTimeMoment * t1,NcvTimeMoment * t2)636     double _ncvMomentsDiffToMicroseconds(NcvTimeMoment *t1, NcvTimeMoment *t2)
637     {
638         return 1000000.0 * 2 * ((t2->moment) - (t1->moment)) / (t1->freq + t2->freq);
639     }
640 
641 
_ncvMomentsDiffToMilliseconds(NcvTimeMoment * t1,NcvTimeMoment * t2)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 
_ncvQueryMoment(NcvTimeMoment * t)658     void _ncvQueryMoment(NcvTimeMoment *t)
659     {
660         gettimeofday(& t->tv, & t->tz);
661     }
662 
663 
_ncvMomentToMicroseconds(NcvTimeMoment * t)664     double _ncvMomentToMicroseconds(NcvTimeMoment *t)
665     {
666         return 1000000.0 * t->tv.tv_sec + (double)t->tv.tv_usec;
667     }
668 
669 
_ncvMomentsDiffToMicroseconds(NcvTimeMoment * t1,NcvTimeMoment * t2)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 
_ncvMomentsDiffToMilliseconds(NcvTimeMoment * t1,NcvTimeMoment * t2)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 
ncvStartTimer(void)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 
ncvEndQueryTimerUs(NcvTimer t)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 
ncvEndQueryTimerMs(NcvTimer t)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 {
operator ()RectConvert726     cv::Rect operator()(const NcvRect32u& nr) const { return cv::Rect(nr.x, nr.y, nr.width, nr.height); }
operator ()RectConvert727     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 
groupRectangles(std::vector<NcvRect32u> & hypotheses,int groupThreshold,double eps,std::vector<Ncv32u> * weights)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 
ncvGroupRectangles_host(NCVVector<NcvRect32u> & hypotheses,Ncv32u & numHypotheses,Ncv32u minNeighbors,Ncv32f intersectEps,NCVVector<Ncv32u> * hypothesesWeights)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>
drawRectsWrapperHost(T * h_dst,Ncv32u dstStride,Ncv32u dstWidth,Ncv32u dstHeight,NcvRect32u * h_rects,Ncv32u numRects,T color)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 
ncvDrawRects_8u_host(Ncv8u * h_dst,Ncv32u dstStride,Ncv32u dstWidth,Ncv32u dstHeight,NcvRect32u * h_rects,Ncv32u numRects,Ncv8u color)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 
ncvDrawRects_32u_host(Ncv32u * h_dst,Ncv32u dstStride,Ncv32u dstWidth,Ncv32u dstHeight,NcvRect32u * h_rects,Ncv32u numRects,Ncv32u color)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