From bf0c316e7aa198507ca683b98034688fb728d0a9 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 21 Jul 2015 19:53:36 -0400 Subject: [PATCH 01/10] re2 fixes for Windows --- src/openalpr/support/re2/re2.cc | 2 ++ src/openalpr/support/re2/util/mutex.h | 6 ++++-- src/openalpr/support/re2/util/stringprintf.cc | 6 +++++- src/openalpr/support/re2/util/strutil.cc | 9 +++++++-- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/openalpr/support/re2/re2.cc b/src/openalpr/support/re2/re2.cc index 28581b6..aea5f6e 100644 --- a/src/openalpr/support/re2/re2.cc +++ b/src/openalpr/support/re2/re2.cc @@ -11,7 +11,9 @@ #include #include +#ifndef WIN32 #include +#endif #include #include "util/atomicops.h" #include "util/util.h" diff --git a/src/openalpr/support/re2/util/mutex.h b/src/openalpr/support/re2/util/mutex.h index f64acb1..19a49d5 100644 --- a/src/openalpr/support/re2/util/mutex.h +++ b/src/openalpr/support/re2/util/mutex.h @@ -14,8 +14,10 @@ namespace re2 { -#define HAVE_PTHREAD 1 -#define HAVE_RWLOCK 1 +#ifndef WIN32 + #define HAVE_PTHREAD 1 + #define HAVE_RWLOCK 1 +#endif #if defined(NO_THREADS) typedef int MutexType; // to keep a lock-count diff --git a/src/openalpr/support/re2/util/stringprintf.cc b/src/openalpr/support/re2/util/stringprintf.cc index e15c550..3c9c14b 100644 --- a/src/openalpr/support/re2/util/stringprintf.cc +++ b/src/openalpr/support/re2/util/stringprintf.cc @@ -38,7 +38,11 @@ static void StringAppendV(string* dst, const char* format, va_list ap) { // Restore the va_list before we use it again va_copy(backup_ap, ap); - result = vsnprintf(buf, length, format, backup_ap); + #ifdef WIN32 + result = vsnprintf_s(buf, length, length, format, backup_ap); + #else + result = vsnprintf(buf, length, format, backup_ap); + #endif va_end(backup_ap); if ((result >= 0) && (result < length)) { diff --git a/src/openalpr/support/re2/util/strutil.cc b/src/openalpr/support/re2/util/strutil.cc index 74116ce..ab28df7 100644 --- a/src/openalpr/support/re2/util/strutil.cc +++ b/src/openalpr/support/re2/util/strutil.cc @@ -1,7 +1,7 @@ // Copyright 1999-2005 The RE2 Authors. All Rights Reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. - +#include #include "re2/util/util.h" #include "re2/stringpiece.h" @@ -38,7 +38,12 @@ int CEscapeString(const char* src, int src_len, char* dest, if (c < ' ' || c > '~') { if (dest_len - used < 5) // space for four-character escape + \0 return -1; - sprintf(dest + used, "\\%03o", c); + #ifdef WIN32 + sprintf_s(dest + used, dest_len, "\\%03o", c); + #else + std::sprintf(dest + used, "\\%03o", c); + #endif + used += 4; } else { dest[used++] = c; break; From 40150505128066eb6fff2c4132bef55f4daacb7e Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Wed, 12 Aug 2015 14:42:30 +0200 Subject: [PATCH 02/10] Optimize motion detector by using BitmapMat for Bitmap^ only. --- .../openalpr-net/motiondetector-net.cpp | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/motiondetector-net.cpp b/src/bindings/csharp/openalpr-net/motiondetector-net.cpp index 63721e9..18b9ed6 100644 --- a/src/bindings/csharp/openalpr-net/motiondetector-net.cpp +++ b/src/bindings/csharp/openalpr-net/motiondetector-net.cpp @@ -14,23 +14,20 @@ void AlprMotionDetectionNet::ResetMotionDetection(Bitmap^ bitmap) void AlprMotionDetectionNet::ResetMotionDetection(String^ filename) { - BitmapMat^ wrapper = gcnew BitmapMat(filename); - ResetMotionDetection(wrapper->Value); - delete wrapper; + cv::Mat mat = cv::imread(marshal_as(filename)); + ResetMotionDetection(mat); } void AlprMotionDetectionNet::ResetMotionDetection(MemoryStream^ memoryStream) { - BitmapMat^ wrapper = gcnew BitmapMat(memoryStream); - ResetMotionDetection(wrapper->Value); - delete wrapper; + return ResetMotionDetection(memoryStream->ToArray()); } void AlprMotionDetectionNet::ResetMotionDetection(array^ byteArray) { - BitmapMat^ wrapper = gcnew BitmapMat(byteArray); - ResetMotionDetection(wrapper->Value); - delete wrapper; + std::vector buffer = AlprHelper::ToVector(byteArray); + cv::Mat mat = cv::imdecode(buffer, 1); + ResetMotionDetection(mat); } System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(Bitmap^ bitmap) @@ -43,26 +40,21 @@ System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(Bitmap^ bitmap) System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(String^ filename) { - BitmapMat^ wrapper = gcnew BitmapMat(filename); - System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); - delete wrapper; + cv::Mat mat = cv::imread(marshal_as(filename)); + System::Drawing::Rectangle motion = MotionDetect(mat); return motion; } System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(MemoryStream^ memoryStream) { - BitmapMat^ wrapper = gcnew BitmapMat(memoryStream); - System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); - delete wrapper; - return motion; + return MotionDetect(memoryStream->ToArray()); } System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(array^ byteArray) { - BitmapMat^ wrapper = gcnew BitmapMat(byteArray); - System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); - delete wrapper; - return motion; + std::vector buffer = AlprHelper::ToVector(byteArray); + cv::Mat mat = cv::imdecode(buffer, 1); + return MotionDetect(mat); } void AlprMotionDetectionNet::ResetMotionDetection(cv::Mat mat) From cd1c55c8b0b8ebd9a9c401c56b10a07fb9ad9e77 Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Wed, 12 Aug 2015 15:41:32 +0200 Subject: [PATCH 03/10] Cleanup BitmapNet class. --- .../csharp/openalpr-net/bitmapmat-net.cpp | 26 +++++-- .../csharp/openalpr-net/bitmapmat-net.h | 69 ++----------------- 2 files changed, 27 insertions(+), 68 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/bitmapmat-net.cpp b/src/bindings/csharp/openalpr-net/bitmapmat-net.cpp index 69db8f7..ba0d669 100644 --- a/src/bindings/csharp/openalpr-net/bitmapmat-net.cpp +++ b/src/bindings/csharp/openalpr-net/bitmapmat-net.cpp @@ -5,23 +5,37 @@ using namespace openalprnet; BitmapMat::BitmapMat(array^ byteArray) { - this->m_bitmap = ByteArrayToMat(byteArray); + m_bitmap = new cv::Mat(); + std::vector buffer = AlprHelper::ToVector(byteArray); + cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR, this->m_bitmap); } BitmapMat::BitmapMat(Bitmap^ bitmap) { - this->m_bitmap = BitmapToMat(bitmap); + m_bitmap = new cv::Mat(); + + MemoryStream^ ms = gcnew MemoryStream(); + bitmap->Save(ms, ImageFormat::Png); + + std::vector buffer = AlprHelper::ToVector(ms->ToArray()); + cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR, this->m_bitmap); + + delete ms; } BitmapMat::BitmapMat(MemoryStream^ memoryStream) { - this->m_bitmap = MemoryStreamBitmapToMat(memoryStream); + m_bitmap = new cv::Mat(); + std::vector buffer = AlprHelper::ToVector(memoryStream->ToArray()); + cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR, this->m_bitmap); } BitmapMat::BitmapMat(String^ filename) { - Bitmap^ bitmap = gcnew Bitmap(filename); - this->m_bitmap = BitmapToMat(bitmap); - delete bitmap; + m_bitmap = new cv::Mat(); + array^ byteArray = File::ReadAllBytes(filename); + std::vector buffer = AlprHelper::ToVector(byteArray); + cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR, this->m_bitmap); + delete byteArray; } diff --git a/src/bindings/csharp/openalpr-net/bitmapmat-net.h b/src/bindings/csharp/openalpr-net/bitmapmat-net.h index cedbf94..3732759 100644 --- a/src/bindings/csharp/openalpr-net/bitmapmat-net.h +++ b/src/bindings/csharp/openalpr-net/bitmapmat-net.h @@ -1,6 +1,9 @@ #pragma once -#include "opencv2/imgproc/imgproc.hpp" +#include +#include + +#include "helper-net.h" using namespace System; using namespace System::Drawing; @@ -33,74 +36,16 @@ namespace openalprnet { !BitmapMat() { - delete[] m_bitmap->data; + m_bitmap->release(); + delete m_bitmap; } property cv::Mat Value { cv::Mat get() { - cv::Mat value = this->m_bitmap->clone(); - return value; + return *m_bitmap; } } - private: - - static cv::Mat* BitmapToMat(Bitmap^ bitmap) - { - int channels = 0; - - switch (bitmap->PixelFormat) - { - case PixelFormat::Format8bppIndexed: - case PixelFormat::Format1bppIndexed: - channels = 1; - break; - case PixelFormat::Format24bppRgb: - channels = 3; - break; - case PixelFormat::Format32bppRgb: - case PixelFormat::Format32bppArgb: - case PixelFormat::Format32bppPArgb: - channels = 4; - break; - default: - throw gcnew NotSupportedException(bitmap->PixelFormat.ToString()); - } - - BitmapData^ bitmapData = bitmap->LockBits( - System::Drawing::Rectangle(0, 0, bitmap->Width, bitmap->Height), - ImageLockMode::ReadOnly, - bitmap->PixelFormat - ); - - const int totalBytes = bitmap->Height * bitmapData->Stride; - - char *dst = new char[totalBytes]; - ::memcpy(dst, bitmapData->Scan0.ToPointer(), totalBytes); - - cv::Mat* dstMat = new cv::Mat(cv::Size(bitmap->Width, bitmap->Height), CV_8UC(channels), dst); - - bitmap->UnlockBits(bitmapData); - - return dstMat; - } - - static cv::Mat* MemoryStreamBitmapToMat(MemoryStream^ memoryStream) - { - Bitmap^ bitmap = gcnew Bitmap(memoryStream); - cv::Mat* mat = BitmapToMat(bitmap); - delete bitmap; - return mat; - } - - static cv::Mat* ByteArrayToMat(array^ byteArray) - { - MemoryStream^ ms = gcnew MemoryStream(byteArray); - cv::Mat* mat = MemoryStreamBitmapToMat(ms); - delete ms; - return mat; - } - }; } \ No newline at end of file From b8f625bed0f594da881adad1c9e7037115e34e6f Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Wed, 12 Aug 2015 15:42:39 +0200 Subject: [PATCH 04/10] Use overload. --- src/bindings/csharp/openalpr-net/openalpr-net.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index d1519c9..b3bfa37 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -361,8 +361,7 @@ namespace openalprnet { /// Recognize from an image on disk /// AlprResultsNet^ Recognize(System::String^ filepath) { - AlprResults results = m_Impl->recognize(marshal_as(filepath)); - return gcnew AlprResultsNet(results); + return Recognize(filepath, gcnew List()); } /// From 6cfb804ad088fdb60a9ddffbcba3f95510c17a8a Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Wed, 12 Aug 2015 15:42:00 +0200 Subject: [PATCH 05/10] Remove cli namespace. --- src/bindings/csharp/openalpr-net/openalpr-net.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index b3bfa37..4ec0d66 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -418,7 +418,7 @@ namespace openalprnet { /// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// /// Bytes representing image data - AlprResultsNet^ Recognize(cli::array^ imageBuffer) { + AlprResultsNet^ Recognize(array^ imageBuffer) { return Recognize(imageBuffer, gcnew List()); } @@ -426,7 +426,7 @@ namespace openalprnet { /// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// /// Bytes representing image data - AlprResultsNet^ Recognize(cli::array^ imageBuffer, List^ regionsOfInterest) { + AlprResultsNet^ Recognize(array^ imageBuffer, List^ regionsOfInterest) { std::vector buffer = AlprHelper::ToVector(imageBuffer); std::vector rois = AlprHelper::ToVector(regionsOfInterest); AlprResults results = m_Impl->recognize(buffer, rois); @@ -436,14 +436,14 @@ namespace openalprnet { /// /// Recognize from raw pixel data /// - AlprResultsNet^ Recognize(cli::array^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight) { + AlprResultsNet^ Recognize(array^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight) { return Recognize(imageBuffer, bytesPerPixel, imgWidth, imgHeight, gcnew List()); } /// /// Recognize from raw pixel data /// - AlprResultsNet^ Recognize(cli::array^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight, List^ regionsOfInterest) { + AlprResultsNet^ Recognize(array^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight, List^ regionsOfInterest) { unsigned char* p = AlprHelper::ToCharPtr(imageBuffer); std::vector rois = AlprHelper::ToVector(regionsOfInterest); AlprResults results = m_Impl->recognize(p, bytesPerPixel, imgWidth, imgHeight, rois); From bdcd318ffe6c4b4c2230fa8a00972e272f9eb4f6 Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Wed, 12 Aug 2015 15:57:18 +0200 Subject: [PATCH 06/10] Use enum value. --- src/bindings/csharp/openalpr-net/motiondetector-net.cpp | 4 ++-- src/bindings/csharp/openalpr-net/openalpr-net.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/motiondetector-net.cpp b/src/bindings/csharp/openalpr-net/motiondetector-net.cpp index 18b9ed6..a9a716b 100644 --- a/src/bindings/csharp/openalpr-net/motiondetector-net.cpp +++ b/src/bindings/csharp/openalpr-net/motiondetector-net.cpp @@ -26,7 +26,7 @@ void AlprMotionDetectionNet::ResetMotionDetection(MemoryStream^ memoryStream) void AlprMotionDetectionNet::ResetMotionDetection(array^ byteArray) { std::vector buffer = AlprHelper::ToVector(byteArray); - cv::Mat mat = cv::imdecode(buffer, 1); + cv::Mat mat = cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR); ResetMotionDetection(mat); } @@ -53,7 +53,7 @@ System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(MemoryStream^ me System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(array^ byteArray) { std::vector buffer = AlprHelper::ToVector(byteArray); - cv::Mat mat = cv::imdecode(buffer, 1); + cv::Mat mat = cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR); return MotionDetect(mat); } diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index 4ec0d66..fb9183b 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -457,7 +457,7 @@ namespace openalprnet { array^ PreWarp(array^ imageBuffer) { std::vector buffer = AlprHelper::ToVector(imageBuffer); - cv::Mat src = cv::imdecode(buffer, 1); + cv::Mat src = cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR); alpr::PreWarp *preWarp = new alpr::PreWarp(m_Impl->getConfig()); cv::Mat warpedImage = preWarp->warpImage(src); From fed3622bf3846bfbf716cce00028b1c5a6e16c16 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 12 Aug 2015 23:26:32 -0400 Subject: [PATCH 07/10] Rearranged timing.h for Windows --- src/openalpr/support/timing.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/openalpr/support/timing.h b/src/openalpr/support/timing.h index 9a022e6..13b8761 100644 --- a/src/openalpr/support/timing.h +++ b/src/openalpr/support/timing.h @@ -1,12 +1,22 @@ -#ifndef TIMING_H -#define TIMING_H +#ifndef OPENALPR_TIMING_H +#define OPENALPR_TIMING_H #include #include #include +#if WINDOWS +struct timespec +{ + time_t tv_sec; // Seconds - >= 0 + long tv_usec; // Nanoseconds - [0, 999999999] +}; +#endif + #ifdef WINDOWS // Import windows only stuff + #include + #else #include #endif @@ -17,13 +27,6 @@ #include #endif -// Support for Windows -#ifdef WINDOWS -#include - -#define timespec timeval -#endif - namespace alpr { From cd9637891092be54edeff579d01982418239484d Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 12 Aug 2015 23:26:52 -0400 Subject: [PATCH 08/10] Updated re2 for Windows compile --- src/openalpr/support/re2/re2.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openalpr/support/re2/re2.cc b/src/openalpr/support/re2/re2.cc index aea5f6e..3f0020f 100644 --- a/src/openalpr/support/re2/re2.cc +++ b/src/openalpr/support/re2/re2.cc @@ -36,7 +36,7 @@ const VariadicFunction2 const VariadicFunction2 RE2::FindAndConsume = {}; // This will trigger LNK2005 error in MSVC. -#ifndef COMPILER_MSVC +#ifndef WIN32 const int RE2::Options::kDefaultMaxMem; // initialized in re2.h #endif // COMPILER_MSVC From 0a776aff31b994f3c599cd006c8f270076b975fe Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 12 Aug 2015 23:27:09 -0400 Subject: [PATCH 09/10] updated re2 for Windows compile --- src/openalpr/support/re2/util/stringprintf.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/openalpr/support/re2/util/stringprintf.cc b/src/openalpr/support/re2/util/stringprintf.cc index 3c9c14b..5f1869f 100644 --- a/src/openalpr/support/re2/util/stringprintf.cc +++ b/src/openalpr/support/re2/util/stringprintf.cc @@ -14,7 +14,12 @@ static void StringAppendV(string* dst, const char* format, va_list ap) { // the data in it upon use. The fix is to make a copy // of the structure before using it and use that copy instead. va_list backup_ap; + + #if defined(WIN32) + backup_ap = ap; + #else va_copy(backup_ap, ap); + #endif int result = vsnprintf(space, sizeof(space), format, backup_ap); va_end(backup_ap); @@ -37,7 +42,12 @@ static void StringAppendV(string* dst, const char* format, va_list ap) { char* buf = new char[length]; // Restore the va_list before we use it again + #if defined(WIN32) + va_list backup_ap = ap; + #else va_copy(backup_ap, ap); + #endif + #ifdef WIN32 result = vsnprintf_s(buf, length, length, format, backup_ap); #else From a63bd87bcbe0590c23328f492529185410eddb6c Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 12 Aug 2015 23:46:37 -0400 Subject: [PATCH 10/10] Added timing fixes for Visual Studio 2015 --- src/openalpr/support/timing.cpp | 12 ++++++------ src/openalpr/support/timing.h | 18 ++++++++++-------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/openalpr/support/timing.cpp b/src/openalpr/support/timing.cpp index 82c8374..222c588 100644 --- a/src/openalpr/support/timing.cpp +++ b/src/openalpr/support/timing.cpp @@ -67,7 +67,7 @@ namespace alpr microseconds = (double)t.QuadPart / frequencyToMicroseconds; t.QuadPart = microseconds; tv->tv_sec = t.QuadPart / 1000000; - tv->tv_usec = t.QuadPart % 1000000; + tv->tv_nsec = t.QuadPart % 1000000; return (0); } @@ -83,7 +83,7 @@ namespace alpr timespec time_start; time_start.tv_sec = 0; - time_start.tv_usec = 0; + time_start.tv_nsec = 0; return diffclock(time_start, time); } @@ -92,7 +92,7 @@ namespace alpr double diffclock(timespec time1,timespec time2) { timespec delta = diff(time1,time2); - double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_usec) / 1000.0); + double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_nsec) / 10000.0); return milliseconds; } @@ -100,15 +100,15 @@ namespace alpr timespec diff(timespec start, timespec end) { timespec temp; - if ((end.tv_usec-start.tv_usec)<0) + if ((end.tv_nsec-start.tv_nsec)<0) { temp.tv_sec = end.tv_sec-start.tv_sec-1; - temp.tv_usec = 1000000+end.tv_usec-start.tv_usec; + temp.tv_nsec = 1000000+end.tv_nsec-start.tv_nsec; } else { temp.tv_sec = end.tv_sec-start.tv_sec; - temp.tv_usec = end.tv_usec-start.tv_usec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; } return temp; } diff --git a/src/openalpr/support/timing.h b/src/openalpr/support/timing.h index 13b8761..cf715cc 100644 --- a/src/openalpr/support/timing.h +++ b/src/openalpr/support/timing.h @@ -5,18 +5,20 @@ #include #include -#if WINDOWS -struct timespec -{ - time_t tv_sec; // Seconds - >= 0 - long tv_usec; // Nanoseconds - [0, 999999999] -}; -#endif + #ifdef WINDOWS // Import windows only stuff #include - + #if _MSC_VER < 1900 + struct timespec + { + time_t tv_sec; // Seconds - >= 0 + long tv_nsec; // Nanoseconds - [0, 999999999] + }; + #else + //#define timespec timeval + #endif #else #include #endif