Skip to content

Commit e5d7896

Browse files
committed
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
2 parents ba8d20e + fba70f7 commit e5d7896

File tree

20 files changed

+283
-215
lines changed

20 files changed

+283
-215
lines changed

modules/core/include/opencv2/core/hal/intrin_neon.hpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,22 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
6262
#define CV_SIMD128_64F 0
6363
#endif
6464

65+
// The following macro checks if the code is being compiled for the
66+
// AArch64 execution state of Armv8, to enable the 128-bit
67+
// intrinsics. The macro `__ARM_64BIT_STATE` is the one recommended by
68+
// the Arm C Language Extension (ACLE) specifications [1] to check the
69+
// availability of 128-bit intrinsics, and it is supporrted by clang
70+
// and gcc. The macro `_M_ARM64` is the equivalent one for Microsoft
71+
// Visual Studio [2] .
72+
//
73+
// [1] https://developer.arm.com/documentation/101028/0012/13--Advanced-SIMD--Neon--intrinsics
74+
// [2] https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
75+
#if defined(__ARM_64BIT_STATE) || defined(_M_ARM64)
76+
#define CV_NEON_AARCH64 1
77+
#else
78+
#define CV_NEON_AARCH64 0
79+
#endif
80+
6581
// TODO
6682
#define CV_NEON_DOT 0
6783

@@ -726,41 +742,61 @@ inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b,
726742
// 16 >> 32
727743
inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b)
728744
{
745+
#if CV_NEON_AARCH64
746+
int32x4_t p = vmull_s16(vget_low_s16(a.val), vget_low_s16(b.val));
747+
return v_int32x4(vmlal_high_s16(p, a.val, b.val));
748+
#else
729749
int16x4_t a0 = vget_low_s16(a.val);
730750
int16x4_t a1 = vget_high_s16(a.val);
731751
int16x4_t b0 = vget_low_s16(b.val);
732752
int16x4_t b1 = vget_high_s16(b.val);
733753
int32x4_t p = vmull_s16(a0, b0);
734754
return v_int32x4(vmlal_s16(p, a1, b1));
755+
#endif
735756
}
736757
inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b, const v_int32x4& c)
737758
{
759+
#if CV_NEON_AARCH64
760+
int32x4_t p = vmlal_s16(c.val, vget_low_s16(a.val), vget_low_s16(b.val));
761+
return v_int32x4(vmlal_high_s16(p, a.val, b.val));
762+
#else
738763
int16x4_t a0 = vget_low_s16(a.val);
739764
int16x4_t a1 = vget_high_s16(a.val);
740765
int16x4_t b0 = vget_low_s16(b.val);
741766
int16x4_t b1 = vget_high_s16(b.val);
742767
int32x4_t p = vmlal_s16(c.val, a0, b0);
743768
return v_int32x4(vmlal_s16(p, a1, b1));
769+
#endif
744770
}
745771

746772
// 32 >> 64
747773
inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b)
748774
{
775+
#if CV_NEON_AARCH64
776+
int64x2_t p = vmull_s32(vget_low_s32(a.val), vget_low_s32(b.val));
777+
return v_int64x2(vmlal_high_s32(p, a.val, b.val));
778+
#else
749779
int32x2_t a0 = vget_low_s32(a.val);
750780
int32x2_t a1 = vget_high_s32(a.val);
751781
int32x2_t b0 = vget_low_s32(b.val);
752782
int32x2_t b1 = vget_high_s32(b.val);
753783
int64x2_t p = vmull_s32(a0, b0);
754784
return v_int64x2(vmlal_s32(p, a1, b1));
785+
#endif
755786
}
756787
inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b, const v_int64x2& c)
757788
{
789+
#if CV_NEON_AARCH64
790+
int64x2_t p = vmlal_s32(c.val, vget_low_s32(a.val), vget_low_s32(b.val));
791+
return v_int64x2(vmlal_high_s32(p, a.val, b.val));
792+
#else
758793
int32x2_t a0 = vget_low_s32(a.val);
759794
int32x2_t a1 = vget_high_s32(a.val);
760795
int32x2_t b0 = vget_low_s32(b.val);
761796
int32x2_t b1 = vget_high_s32(b.val);
762797
int64x2_t p = vmlal_s32(c.val, a0, b0);
763798
return v_int64x2(vmlal_s32(p, a1, b1));
799+
#endif
764800
}
765801

766802
// 8 >> 32
@@ -1292,7 +1328,7 @@ inline int64 v_reduce_sum(const v_int64x2& a)
12921328
#if CV_SIMD128_64F
12931329
inline double v_reduce_sum(const v_float64x2& a)
12941330
{
1295-
return vgetq_lane_f64(a.val, 0) + vgetq_lane_f64(a.val, 1);
1331+
return vaddvq_f64(a.val);
12961332
}
12971333
#endif
12981334

modules/core/src/parallel_impl.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,16 @@ class ParallelJob
356356
};
357357

358358

359+
// Disable thread sanitization check when CV_USE_GLOBAL_WORKERS_COND_VAR is not
360+
// set because it triggers as the main thread reads isActive while the children
361+
// thread writes it (but it all works out because a mutex is locked in the main
362+
// thread and isActive re-checked).
363+
// This is to solve issue #19463.
364+
#if !defined(CV_USE_GLOBAL_WORKERS_COND_VAR) && defined(__clang__) && defined(__has_feature)
365+
#if __has_feature(thread_sanitizer)
366+
__attribute__((no_sanitize("thread")))
367+
#endif
368+
#endif
359369
void WorkerThread::thread_body()
360370
{
361371
(void)cv::utils::getThreadID(); // notify OpenCV about new thread

modules/imgcodecs/CMakeLists.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@ if(HAVE_WINRT_CX AND NOT WINRT)
1313
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /ZW")
1414
endif()
1515

16-
if(HAVE_PNG OR HAVE_TIFF OR HAVE_OPENEXR)
17-
ocv_include_directories(${ZLIB_INCLUDE_DIRS})
18-
list(APPEND GRFMT_LIBS ${ZLIB_LIBRARIES})
19-
endif()
20-
2116
if(HAVE_JPEG)
2217
ocv_include_directories(${JPEG_INCLUDE_DIR} ${${JPEG_LIBRARY}_BINARY_DIR})
2318
list(APPEND GRFMT_LIBS ${JPEG_LIBRARIES})
@@ -63,6 +58,11 @@ if(HAVE_OPENEXR)
6358
list(APPEND GRFMT_LIBS ${OPENEXR_LIBRARIES})
6459
endif()
6560

61+
if(HAVE_PNG OR HAVE_TIFF OR HAVE_OPENEXR)
62+
ocv_include_directories(${ZLIB_INCLUDE_DIRS})
63+
list(APPEND GRFMT_LIBS ${ZLIB_LIBRARIES})
64+
endif()
65+
6666
if(HAVE_GDAL)
6767
include_directories(SYSTEM ${GDAL_INCLUDE_DIR})
6868
list(APPEND GRFMT_LIBS ${GDAL_LIBRARY})

modules/imgcodecs/src/exif.cpp

Lines changed: 25 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ ExifEntry_t::ExifEntry_t() :
6262
/**
6363
* @brief ExifReader constructor
6464
*/
65-
ExifReader::ExifReader(std::istream& stream) : m_stream(stream), m_format(NONE)
65+
ExifReader::ExifReader() : m_format(NONE)
6666
{
6767
}
6868

@@ -73,25 +73,6 @@ ExifReader::~ExifReader()
7373
{
7474
}
7575

76-
/**
77-
* @brief Parsing the file and prepare (internally) exif directory structure
78-
* @return true if parsing was successful and exif information exists in JpegReader object
79-
* false in case of unsuccessful parsing
80-
*/
81-
bool ExifReader::parse()
82-
{
83-
try {
84-
m_exif = getExif();
85-
if( !m_exif.empty() )
86-
{
87-
return true;
88-
}
89-
return false;
90-
} catch (ExifParsingError&) {
91-
return false;
92-
}
93-
}
94-
9576

9677
/**
9778
* @brief Get tag value by tag number
@@ -101,10 +82,10 @@ bool ExifReader::parse()
10182
* @return ExifEntru_t structure. Caller has to know what tag it calls in order to extract proper field from the structure ExifEntry_t
10283
*
10384
*/
104-
ExifEntry_t ExifReader::getTag(const ExifTagName tag)
85+
ExifEntry_t ExifReader::getTag(const ExifTagName tag) const
10586
{
10687
ExifEntry_t entry;
107-
std::map<int, ExifEntry_t>::iterator it = m_exif.find(tag);
88+
std::map<int, ExifEntry_t>::const_iterator it = m_exif.find(tag);
10889

10990
if( it != m_exif.end() )
11091
{
@@ -115,100 +96,37 @@ ExifEntry_t ExifReader::getTag(const ExifTagName tag)
11596

11697

11798
/**
118-
* @brief Get exif directory structure contained in file (if any)
119-
* This is internal function and is not exposed to client
99+
* @brief Parsing the exif data buffer and prepare (internal) exif directory
100+
*
101+
* @param [in] data The data buffer to read EXIF data starting with endianness
102+
* @param [in] size The size of the data buffer
120103
*
121-
* @return Map where key is tag number and value is ExifEntry_t structure
104+
* @return true if parsing was successful
105+
* false in case of unsuccessful parsing
122106
*/
123-
std::map<int, ExifEntry_t > ExifReader::getExif()
107+
bool ExifReader::parseExif(unsigned char* data, const size_t size)
124108
{
125-
const std::streamsize markerSize = 2;
126-
const std::streamsize offsetToTiffHeader = 6; //bytes from Exif size field to the first TIFF header
127-
unsigned char appMarker[markerSize];
128-
m_exif.erase( m_exif.begin(), m_exif.end() );
129-
130-
std::streamsize count;
131-
132-
bool exifFound = false, stopSearch = false;
133-
while( ( !m_stream.eof() ) && !exifFound && !stopSearch )
109+
// Populate m_data, then call parseExif() (private)
110+
if( data && size > 0 )
134111
{
135-
m_stream.read( reinterpret_cast<char*>(appMarker), markerSize );
136-
count = m_stream.gcount();
137-
if( count < markerSize )
138-
{
139-
break;
140-
}
141-
unsigned char marker = appMarker[1];
142-
size_t bytesToSkip;
143-
size_t exifSize;
144-
switch( marker )
145-
{
146-
//For all the markers just skip bytes in file pointed by followed two bytes (field size)
147-
case SOF0: case SOF2: case DHT: case DQT: case DRI: case SOS:
148-
case RST0: case RST1: case RST2: case RST3: case RST4: case RST5: case RST6: case RST7:
149-
case APP0: case APP2: case APP3: case APP4: case APP5: case APP6: case APP7: case APP8:
150-
case APP9: case APP10: case APP11: case APP12: case APP13: case APP14: case APP15:
151-
case COM:
152-
bytesToSkip = getFieldSize();
153-
if (bytesToSkip < markerSize) {
154-
throw ExifParsingError();
155-
}
156-
m_stream.seekg( static_cast<long>( bytesToSkip - markerSize ), m_stream.cur );
157-
if ( m_stream.fail() ) {
158-
throw ExifParsingError();
159-
}
160-
break;
161-
162-
//SOI and EOI don't have the size field after the marker
163-
case SOI: case EOI:
164-
break;
165-
166-
case APP1: //actual Exif Marker
167-
exifSize = getFieldSize();
168-
if (exifSize <= offsetToTiffHeader) {
169-
throw ExifParsingError();
170-
}
171-
m_data.resize( exifSize - offsetToTiffHeader );
172-
m_stream.seekg( static_cast<long>( offsetToTiffHeader ), m_stream.cur );
173-
if ( m_stream.fail() ) {
174-
throw ExifParsingError();
175-
}
176-
m_stream.read( reinterpret_cast<char*>(&m_data[0]), exifSize - offsetToTiffHeader );
177-
exifFound = true;
178-
break;
179-
180-
default: //No other markers are expected according to standard. May be a signal of error
181-
stopSearch = true;
182-
break;
183-
}
112+
m_data.assign(data, data + size);
184113
}
185-
186-
if( !exifFound )
114+
else
187115
{
188-
return m_exif;
116+
return false;
189117
}
190118

191-
parseExif();
192-
193-
return m_exif;
194-
}
195-
196-
/**
197-
* @brief Get the size of exif field (required to properly ready whole exif from the file)
198-
* This is internal function and is not exposed to client
199-
*
200-
* @return size of exif field in the file
201-
*/
202-
size_t ExifReader::getFieldSize ()
203-
{
204-
unsigned char fieldSize[2];
205-
m_stream.read( reinterpret_cast<char*>(fieldSize), 2 );
206-
std::streamsize count = m_stream.gcount();
207-
if (count < 2)
208-
{
209-
return 0;
119+
try {
120+
parseExif();
121+
if( !m_exif.empty() )
122+
{
123+
return true;
124+
}
125+
return false;
126+
}
127+
catch( ExifParsingError& ) {
128+
return false;
210129
}
211-
return ( fieldSize[0] << 8 ) + fieldSize[1];
212130
}
213131

214132
/**

modules/imgcodecs/src/exif.hpp

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -54,24 +54,6 @@
5454

5555
namespace cv
5656
{
57-
/**
58-
* @brief Jpeg markers that can encounter in Jpeg file
59-
*/
60-
enum AppMarkerTypes
61-
{
62-
SOI = 0xD8, SOF0 = 0xC0, SOF2 = 0xC2, DHT = 0xC4,
63-
DQT = 0xDB, DRI = 0xDD, SOS = 0xDA,
64-
65-
RST0 = 0xD0, RST1 = 0xD1, RST2 = 0xD2, RST3 = 0xD3,
66-
RST4 = 0xD4, RST5 = 0xD5, RST6 = 0xD6, RST7 = 0xD7,
67-
68-
APP0 = 0xE0, APP1 = 0xE1, APP2 = 0xE2, APP3 = 0xE3,
69-
APP4 = 0xE4, APP5 = 0xE5, APP6 = 0xE6, APP7 = 0xE7,
70-
APP8 = 0xE8, APP9 = 0xE9, APP10 = 0xEA, APP11 = 0xEB,
71-
APP12 = 0xEC, APP13 = 0xED, APP14 = 0xEE, APP15 = 0xEF,
72-
73-
COM = 0xFE, EOI = 0xD9
74-
};
7557

7658
/**
7759
* @brief Base Exif tags used by IFD0 (main image)
@@ -168,38 +150,40 @@ class ExifReader
168150
public:
169151
/**
170152
* @brief ExifReader constructor. Constructs an object of exif reader
171-
*
172-
* @param [in]stream An istream to look for EXIF bytes from
173153
*/
174-
explicit ExifReader( std::istream& stream );
154+
ExifReader();
175155
~ExifReader();
176156

177157

178158
/**
179159
* @brief Parse the file with exif info
180160
*
181-
* @return true if parsing was successful and exif information exists in JpegReader object
161+
* @param [in] data The data buffer to read EXIF data starting with endianness
162+
* @param [in] size The size of the data buffer
163+
*
164+
* @return true if successful parsing
165+
* false if parsing error
182166
*/
183-
bool parse();
167+
168+
bool parseExif(unsigned char* data, const size_t size);
184169

185170
/**
186171
* @brief Get tag info by tag number
187172
*
188173
* @param [in] tag The tag number
189174
* @return ExifEntru_t structure. Caller has to know what tag it calls in order to extract proper field from the structure ExifEntry_t
190175
*/
191-
ExifEntry_t getTag( const ExifTagName tag );
176+
ExifEntry_t getTag( const ExifTagName tag ) const;
177+
192178

193179
private:
194-
std::istream& m_stream;
195180
std::vector<unsigned char> m_data;
196181
std::map<int, ExifEntry_t > m_exif;
197182
Endianess_t m_format;
198183

199184
void parseExif();
200185
bool checkTagMark() const;
201186

202-
size_t getFieldSize ();
203187
size_t getNumDirEntry( const size_t offsetNumDir ) const;
204188
uint32_t getStartOffset() const;
205189
uint16_t getExifTag( const size_t offset ) const;
@@ -215,7 +199,6 @@ class ExifReader
215199

216200
u_rational_t getURational( const size_t offset ) const;
217201

218-
std::map<int, ExifEntry_t > getExif();
219202
std::string getString( const size_t offset ) const;
220203
std::vector<u_rational_t> getResolution( const size_t offset ) const;
221204
std::vector<u_rational_t> getWhitePoint( const size_t offset ) const;

modules/imgcodecs/src/grfmt_base.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ BaseImageDecoder::BaseImageDecoder()
5555
m_scale_denom = 1;
5656
}
5757

58+
59+
ExifEntry_t BaseImageDecoder::getExifTag(const ExifTagName tag) const
60+
{
61+
return m_exif.getTag(tag);
62+
}
5863
bool BaseImageDecoder::setSource( const String& filename )
5964
{
6065
m_filename = filename;

0 commit comments

Comments
 (0)