mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
Merge branch 4.x
This commit is contained in:
Vendored
+1
-1
@@ -1 +1 @@
|
||||
Origin: https://github.com/google/flatbuffers/tree/v23.5.9
|
||||
Origin: https://github.com/google/flatbuffers/tree/v25.9.23
|
||||
|
||||
+5
-5
@@ -28,21 +28,21 @@ class Allocator {
|
||||
virtual ~Allocator() {}
|
||||
|
||||
// Allocate `size` bytes of memory.
|
||||
virtual uint8_t *allocate(size_t size) = 0;
|
||||
virtual uint8_t* allocate(size_t size) = 0;
|
||||
|
||||
// Deallocate `size` bytes of memory at `p` allocated by this allocator.
|
||||
virtual void deallocate(uint8_t *p, size_t size) = 0;
|
||||
virtual void deallocate(uint8_t* p, size_t size) = 0;
|
||||
|
||||
// Reallocate `new_size` bytes of memory, replacing the old region of size
|
||||
// `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
|
||||
// and is intended specifcally for `vector_downward` use.
|
||||
// `in_use_back` and `in_use_front` indicate how much of `old_size` is
|
||||
// actually in use at each end, and needs to be copied.
|
||||
virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
|
||||
virtual uint8_t* reallocate_downward(uint8_t* old_p, size_t old_size,
|
||||
size_t new_size, size_t in_use_back,
|
||||
size_t in_use_front) {
|
||||
FLATBUFFERS_ASSERT(new_size > old_size); // vector_downward only grows
|
||||
uint8_t *new_p = allocate(new_size);
|
||||
uint8_t* new_p = allocate(new_size);
|
||||
memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
|
||||
in_use_front);
|
||||
deallocate(old_p, old_size);
|
||||
@@ -54,7 +54,7 @@ class Allocator {
|
||||
// to `new_p` of `new_size`. Only memory of size `in_use_front` and
|
||||
// `in_use_back` will be copied from the front and back of the old memory
|
||||
// allocation.
|
||||
void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p,
|
||||
void memcpy_downward(uint8_t* old_p, size_t old_size, uint8_t* new_p,
|
||||
size_t new_size, size_t in_use_back,
|
||||
size_t in_use_front) {
|
||||
memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
|
||||
|
||||
+49
-48
@@ -27,17 +27,15 @@
|
||||
namespace flatbuffers {
|
||||
|
||||
// This is used as a helper type for accessing arrays.
|
||||
template<typename T, uint16_t length> class Array {
|
||||
template <typename T, uint16_t length>
|
||||
class Array {
|
||||
// Array<T> can carry only POD data types (scalars or structs).
|
||||
typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
|
||||
scalar_tag;
|
||||
typedef
|
||||
typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type
|
||||
IndirectHelperType;
|
||||
|
||||
public:
|
||||
typedef uint16_t size_type;
|
||||
typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
|
||||
typedef typename IndirectHelper<T>::return_type return_type;
|
||||
typedef VectorConstIterator<T, return_type, uoffset_t> const_iterator;
|
||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
@@ -50,7 +48,7 @@ template<typename T, uint16_t length> class Array {
|
||||
|
||||
return_type Get(uoffset_t i) const {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
return IndirectHelper<IndirectHelperType>::Read(Data(), i);
|
||||
return IndirectHelper<T>::Read(Data(), i);
|
||||
}
|
||||
|
||||
return_type operator[](uoffset_t i) const { return Get(i); }
|
||||
@@ -58,7 +56,8 @@ template<typename T, uint16_t length> class Array {
|
||||
// If this is a Vector of enums, T will be its storage type, not the enum
|
||||
// type. This function makes it convenient to retrieve value with enum
|
||||
// type E.
|
||||
template<typename E> E GetEnum(uoffset_t i) const {
|
||||
template <typename E>
|
||||
E GetEnum(uoffset_t i) const {
|
||||
return static_cast<E>(Get(i));
|
||||
}
|
||||
|
||||
@@ -83,28 +82,28 @@ template<typename T, uint16_t length> class Array {
|
||||
// operation. For primitive types use @p Mutate directly.
|
||||
// @warning Assignments and reads to/from the dereferenced pointer are not
|
||||
// automatically converted to the correct endianness.
|
||||
typename flatbuffers::conditional<scalar_tag::value, void, T *>::type
|
||||
typename flatbuffers::conditional<scalar_tag::value, void, T*>::type
|
||||
GetMutablePointer(uoffset_t i) const {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
return const_cast<T *>(&data()[i]);
|
||||
return const_cast<T*>(&data()[i]);
|
||||
}
|
||||
|
||||
// Change elements if you have a non-const pointer to this object.
|
||||
void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); }
|
||||
void Mutate(uoffset_t i, const T& val) { MutateImpl(scalar_tag(), i, val); }
|
||||
|
||||
// The raw data in little endian format. Use with care.
|
||||
const uint8_t *Data() const { return data_; }
|
||||
const uint8_t* Data() const { return data_; }
|
||||
|
||||
uint8_t *Data() { return data_; }
|
||||
uint8_t* Data() { return data_; }
|
||||
|
||||
// Similarly, but typed, much like std::vector::data
|
||||
const T *data() const { return reinterpret_cast<const T *>(Data()); }
|
||||
T *data() { return reinterpret_cast<T *>(Data()); }
|
||||
const T* data() const { return reinterpret_cast<const T*>(Data()); }
|
||||
T* data() { return reinterpret_cast<T*>(Data()); }
|
||||
|
||||
// Copy data from a span with endian conversion.
|
||||
// If this Array and the span overlap, the behavior is undefined.
|
||||
void CopyFromSpan(flatbuffers::span<const T, length> src) {
|
||||
const auto p1 = reinterpret_cast<const uint8_t *>(src.data());
|
||||
const auto p1 = reinterpret_cast<const uint8_t*>(src.data());
|
||||
const auto p2 = Data();
|
||||
FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) &&
|
||||
!(p2 >= p1 && p2 < (p1 + length)));
|
||||
@@ -114,12 +113,12 @@ template<typename T, uint16_t length> class Array {
|
||||
}
|
||||
|
||||
protected:
|
||||
void MutateImpl(flatbuffers::true_type, uoffset_t i, const T &val) {
|
||||
void MutateImpl(flatbuffers::true_type, uoffset_t i, const T& val) {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
WriteScalar(data() + i, val);
|
||||
}
|
||||
|
||||
void MutateImpl(flatbuffers::false_type, uoffset_t i, const T &val) {
|
||||
void MutateImpl(flatbuffers::false_type, uoffset_t i, const T& val) {
|
||||
*(GetMutablePointer(i)) = val;
|
||||
}
|
||||
|
||||
@@ -134,7 +133,9 @@ template<typename T, uint16_t length> class Array {
|
||||
// Copy data from flatbuffers::span with endian conversion.
|
||||
void CopyFromSpanImpl(flatbuffers::false_type,
|
||||
flatbuffers::span<const T, length> src) {
|
||||
for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); }
|
||||
for (size_type k = 0; k < length; k++) {
|
||||
Mutate(k, src[k]);
|
||||
}
|
||||
}
|
||||
|
||||
// This class is only used to access pre-existing data. Don't ever
|
||||
@@ -153,21 +154,21 @@ template<typename T, uint16_t length> class Array {
|
||||
private:
|
||||
// This class is a pointer. Copying will therefore create an invalid object.
|
||||
// Private and unimplemented copy constructor.
|
||||
Array(const Array &);
|
||||
Array &operator=(const Array &);
|
||||
Array(const Array&);
|
||||
Array& operator=(const Array&);
|
||||
};
|
||||
|
||||
// Specialization for Array[struct] with access using Offset<void> pointer.
|
||||
// This specialization used by idl_gen_text.cpp.
|
||||
template<typename T, uint16_t length, template<typename> class OffsetT>
|
||||
template <typename T, uint16_t length, template <typename> class OffsetT>
|
||||
class Array<OffsetT<T>, length> {
|
||||
static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
|
||||
|
||||
public:
|
||||
typedef const void *return_type;
|
||||
typedef const void* return_type;
|
||||
typedef uint16_t size_type;
|
||||
|
||||
const uint8_t *Data() const { return data_; }
|
||||
const uint8_t* Data() const { return data_; }
|
||||
|
||||
// Make idl_gen_text.cpp::PrintContainer happy.
|
||||
return_type operator[](uoffset_t) const {
|
||||
@@ -178,14 +179,14 @@ class Array<OffsetT<T>, length> {
|
||||
private:
|
||||
// This class is only used to access pre-existing data.
|
||||
Array();
|
||||
Array(const Array &);
|
||||
Array &operator=(const Array &);
|
||||
Array(const Array&);
|
||||
Array& operator=(const Array&);
|
||||
|
||||
uint8_t data_[1];
|
||||
};
|
||||
|
||||
template<class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U, N> make_span(Array<U, N> &arr)
|
||||
template <class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U, N> make_span(Array<U, N>& arr)
|
||||
FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(
|
||||
Array<U, N>::is_span_observable,
|
||||
@@ -193,26 +194,26 @@ FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U, N> make_span(Array<U, N> &arr)
|
||||
return span<U, N>(arr.data(), N);
|
||||
}
|
||||
|
||||
template<class U, uint16_t N>
|
||||
template <class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U, N> make_span(
|
||||
const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
const Array<U, N>& arr) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(
|
||||
Array<U, N>::is_span_observable,
|
||||
"wrong type U, only plain struct, LE-scalar, or byte types are allowed");
|
||||
return span<const U, N>(arr.data(), N);
|
||||
}
|
||||
|
||||
template<class U, uint16_t N>
|
||||
template <class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t, sizeof(U) * N>
|
||||
make_bytes_span(Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
make_bytes_span(Array<U, N>& arr) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Array<U, N>::is_span_observable,
|
||||
"internal error, Array<T> might hold only scalars or structs");
|
||||
return span<uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
|
||||
}
|
||||
|
||||
template<class U, uint16_t N>
|
||||
template <class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t, sizeof(U) * N>
|
||||
make_bytes_span(const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
make_bytes_span(const Array<U, N>& arr) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Array<U, N>::is_span_observable,
|
||||
"internal error, Array<T> might hold only scalars or structs");
|
||||
return span<const uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
|
||||
@@ -221,31 +222,31 @@ make_bytes_span(const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
// Cast a raw T[length] to a raw flatbuffers::Array<T, length>
|
||||
// without endian conversion. Use with care.
|
||||
// TODO: move these Cast-methods to `internal` namespace.
|
||||
template<typename T, uint16_t length>
|
||||
Array<T, length> &CastToArray(T (&arr)[length]) {
|
||||
return *reinterpret_cast<Array<T, length> *>(arr);
|
||||
template <typename T, uint16_t length>
|
||||
Array<T, length>& CastToArray(T (&arr)[length]) {
|
||||
return *reinterpret_cast<Array<T, length>*>(arr);
|
||||
}
|
||||
|
||||
template<typename T, uint16_t length>
|
||||
const Array<T, length> &CastToArray(const T (&arr)[length]) {
|
||||
return *reinterpret_cast<const Array<T, length> *>(arr);
|
||||
template <typename T, uint16_t length>
|
||||
const Array<T, length>& CastToArray(const T (&arr)[length]) {
|
||||
return *reinterpret_cast<const Array<T, length>*>(arr);
|
||||
}
|
||||
|
||||
template<typename E, typename T, uint16_t length>
|
||||
Array<E, length> &CastToArrayOfEnum(T (&arr)[length]) {
|
||||
template <typename E, typename T, uint16_t length>
|
||||
Array<E, length>& CastToArrayOfEnum(T (&arr)[length]) {
|
||||
static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
|
||||
return *reinterpret_cast<Array<E, length> *>(arr);
|
||||
return *reinterpret_cast<Array<E, length>*>(arr);
|
||||
}
|
||||
|
||||
template<typename E, typename T, uint16_t length>
|
||||
const Array<E, length> &CastToArrayOfEnum(const T (&arr)[length]) {
|
||||
template <typename E, typename T, uint16_t length>
|
||||
const Array<E, length>& CastToArrayOfEnum(const T (&arr)[length]) {
|
||||
static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
|
||||
return *reinterpret_cast<const Array<E, length> *>(arr);
|
||||
return *reinterpret_cast<const Array<E, length>*>(arr);
|
||||
}
|
||||
|
||||
template<typename T, uint16_t length>
|
||||
bool operator==(const Array<T, length> &lhs,
|
||||
const Array<T, length> &rhs) noexcept {
|
||||
template <typename T, uint16_t length>
|
||||
bool operator==(const Array<T, length>& lhs,
|
||||
const Array<T, length>& rhs) noexcept {
|
||||
return std::addressof(lhs) == std::addressof(rhs) ||
|
||||
(lhs.size() == rhs.size() &&
|
||||
std::memcmp(lhs.Data(), rhs.Data(), rhs.size() * sizeof(T)) == 0);
|
||||
|
||||
+30
-22
@@ -139,9 +139,9 @@
|
||||
#endif
|
||||
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||
|
||||
#define FLATBUFFERS_VERSION_MAJOR 23
|
||||
#define FLATBUFFERS_VERSION_MINOR 5
|
||||
#define FLATBUFFERS_VERSION_REVISION 9
|
||||
#define FLATBUFFERS_VERSION_MAJOR 25
|
||||
#define FLATBUFFERS_VERSION_MINOR 9
|
||||
#define FLATBUFFERS_VERSION_REVISION 23
|
||||
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
||||
namespace flatbuffers {
|
||||
@@ -155,7 +155,7 @@ namespace flatbuffers {
|
||||
#define FLATBUFFERS_FINAL_CLASS final
|
||||
#define FLATBUFFERS_OVERRIDE override
|
||||
#define FLATBUFFERS_EXPLICIT_CPP11 explicit
|
||||
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t
|
||||
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : ::flatbuffers::voffset_t
|
||||
#else
|
||||
#define FLATBUFFERS_FINAL_CLASS
|
||||
#define FLATBUFFERS_OVERRIDE
|
||||
@@ -279,20 +279,22 @@ namespace flatbuffers {
|
||||
#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
|
||||
|
||||
// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
|
||||
// - __suppress_ubsan__("undefined")
|
||||
// - __suppress_ubsan__("signed-integer-overflow")
|
||||
// - FLATBUFFERS_SUPPRESS_UBSAN("undefined")
|
||||
// - FLATBUFFERS_SUPPRESS_UBSAN("signed-integer-overflow")
|
||||
#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))
|
||||
#define __suppress_ubsan__(type) __attribute__((no_sanitize(type)))
|
||||
#define FLATBUFFERS_SUPPRESS_UBSAN(type) __attribute__((no_sanitize(type)))
|
||||
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
|
||||
#define __suppress_ubsan__(type) __attribute__((no_sanitize_undefined))
|
||||
#define FLATBUFFERS_SUPPRESS_UBSAN(type) __attribute__((no_sanitize_undefined))
|
||||
#else
|
||||
#define __suppress_ubsan__(type)
|
||||
#define FLATBUFFERS_SUPPRESS_UBSAN(type)
|
||||
#endif
|
||||
|
||||
// This is constexpr function used for checking compile-time constants.
|
||||
// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
|
||||
template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
|
||||
return !!t;
|
||||
namespace flatbuffers {
|
||||
// This is constexpr function used for checking compile-time constants.
|
||||
// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
|
||||
template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
|
||||
return !!t;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable C++ attribute [[]] if std:c++17 or higher.
|
||||
@@ -337,15 +339,15 @@ typedef uint16_t voffset_t;
|
||||
typedef uintmax_t largest_scalar_t;
|
||||
|
||||
// In 32bits, this evaluates to 2GB - 1
|
||||
#define FLATBUFFERS_MAX_BUFFER_SIZE std::numeric_limits<::flatbuffers::soffset_t>::max()
|
||||
#define FLATBUFFERS_MAX_64_BUFFER_SIZE std::numeric_limits<::flatbuffers::soffset64_t>::max()
|
||||
#define FLATBUFFERS_MAX_BUFFER_SIZE (std::numeric_limits<::flatbuffers::soffset_t>::max)()
|
||||
#define FLATBUFFERS_MAX_64_BUFFER_SIZE (std::numeric_limits<::flatbuffers::soffset64_t>::max)()
|
||||
|
||||
// The minimum size buffer that can be a valid flatbuffer.
|
||||
// Includes the offset to the root table (uoffset_t), the offset to the vtable
|
||||
// of the root table (soffset_t), the size of the vtable (uint16_t), and the
|
||||
// size of the referring table (uint16_t).
|
||||
#define FLATBUFFERS_MIN_BUFFER_SIZE sizeof(uoffset_t) + sizeof(soffset_t) + \
|
||||
sizeof(uint16_t) + sizeof(uint16_t)
|
||||
#define FLATBUFFERS_MIN_BUFFER_SIZE sizeof(::flatbuffers::uoffset_t) + \
|
||||
sizeof(::flatbuffers::soffset_t) + sizeof(uint16_t) + sizeof(uint16_t)
|
||||
|
||||
// We support aligning the contents of buffers up to this size.
|
||||
#ifndef FLATBUFFERS_MAX_ALIGNMENT
|
||||
@@ -361,7 +363,6 @@ inline bool VerifyAlignmentRequirements(size_t align, size_t min_align = 1) {
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable: 4351) // C4351: new behavior: elements of array ... will be default initialized
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // C4127: conditional expression is constant
|
||||
#endif
|
||||
@@ -422,7 +423,7 @@ template<typename T> T EndianScalar(T t) {
|
||||
|
||||
template<typename T>
|
||||
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
|
||||
__suppress_ubsan__("alignment")
|
||||
FLATBUFFERS_SUPPRESS_UBSAN("alignment")
|
||||
T ReadScalar(const void *p) {
|
||||
return EndianScalar(*reinterpret_cast<const T *>(p));
|
||||
}
|
||||
@@ -436,13 +437,13 @@ T ReadScalar(const void *p) {
|
||||
|
||||
template<typename T>
|
||||
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
|
||||
__suppress_ubsan__("alignment")
|
||||
FLATBUFFERS_SUPPRESS_UBSAN("alignment")
|
||||
void WriteScalar(void *p, T t) {
|
||||
*reinterpret_cast<T *>(p) = EndianScalar(t);
|
||||
}
|
||||
|
||||
template<typename T> struct Offset;
|
||||
template<typename T> __suppress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
|
||||
template<typename T> FLATBUFFERS_SUPPRESS_UBSAN("alignment") void WriteScalar(void *p, Offset<T> t) {
|
||||
*reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o);
|
||||
}
|
||||
|
||||
@@ -453,15 +454,22 @@ template<typename T> __suppress_ubsan__("alignment") void WriteScalar(void *p, O
|
||||
// Computes how many bytes you'd have to pad to be able to write an
|
||||
// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
|
||||
// memory).
|
||||
__suppress_ubsan__("unsigned-integer-overflow")
|
||||
FLATBUFFERS_SUPPRESS_UBSAN("unsigned-integer-overflow")
|
||||
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
|
||||
return ((~buf_size) + 1) & (scalar_size - 1);
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
// Generic 'operator==' with conditional specialisations.
|
||||
// T e - new value of a scalar field.
|
||||
// T def - default of scalar (is known at compile-time).
|
||||
template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
|
||||
#if !defined(_MSC_VER)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#if defined(FLATBUFFERS_NAN_DEFAULTS) && \
|
||||
defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
|
||||
|
||||
+65
-39
@@ -20,12 +20,14 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
#include "flatbuffers/stl_emulation.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Wrapper for uoffset_t to allow safe template specialization.
|
||||
// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
|
||||
template<typename T = void> struct Offset {
|
||||
template <typename T = void>
|
||||
struct Offset {
|
||||
// The type of offset to use.
|
||||
typedef uoffset_t offset_type;
|
||||
|
||||
@@ -36,8 +38,14 @@ template<typename T = void> struct Offset {
|
||||
bool IsNull() const { return !o; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_specialisation_of_Offset : false_type {};
|
||||
template <typename T>
|
||||
struct is_specialisation_of_Offset<Offset<T>> : true_type {};
|
||||
|
||||
// Wrapper for uoffset64_t Offsets.
|
||||
template<typename T = void> struct Offset64 {
|
||||
template <typename T = void>
|
||||
struct Offset64 {
|
||||
// The type of offset to use.
|
||||
typedef uoffset64_t offset_type;
|
||||
|
||||
@@ -48,6 +56,11 @@ template<typename T = void> struct Offset64 {
|
||||
bool IsNull() const { return !o; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_specialisation_of_Offset64 : false_type {};
|
||||
template <typename T>
|
||||
struct is_specialisation_of_Offset64<Offset64<T>> : true_type {};
|
||||
|
||||
// Litmus check for ensuring the Offsets are the expected size.
|
||||
static_assert(sizeof(Offset<>) == 4, "Offset has wrong size");
|
||||
static_assert(sizeof(Offset64<>) == 8, "Offset64 has wrong size");
|
||||
@@ -55,12 +68,13 @@ static_assert(sizeof(Offset64<>) == 8, "Offset64 has wrong size");
|
||||
inline void EndianCheck() {
|
||||
int endiantest = 1;
|
||||
// If this fails, see FLATBUFFERS_LITTLEENDIAN above.
|
||||
FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) ==
|
||||
FLATBUFFERS_ASSERT(*reinterpret_cast<char*>(&endiantest) ==
|
||||
FLATBUFFERS_LITTLEENDIAN);
|
||||
(void)endiantest;
|
||||
}
|
||||
|
||||
template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
|
||||
template <typename T>
|
||||
FLATBUFFERS_CONSTEXPR size_t AlignOf() {
|
||||
// clang-format off
|
||||
#ifdef _MSC_VER
|
||||
return __alignof(T);
|
||||
@@ -76,8 +90,8 @@ template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
|
||||
|
||||
// Lexicographically compare two strings (possibly containing nulls), and
|
||||
// return true if the first is less than the second.
|
||||
static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
|
||||
const char *b_data, uoffset_t b_size) {
|
||||
static inline bool StringLessThan(const char* a_data, uoffset_t a_size,
|
||||
const char* b_data, uoffset_t b_size) {
|
||||
const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
|
||||
return cmp == 0 ? a_size < b_size : cmp < 0;
|
||||
}
|
||||
@@ -90,42 +104,43 @@ static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
|
||||
// return type like this.
|
||||
// The typedef is for the convenience of callers of this function
|
||||
// (avoiding the need for a trailing return decltype)
|
||||
template<typename T> struct IndirectHelper {
|
||||
template <typename T, typename Enable = void>
|
||||
struct IndirectHelper {
|
||||
typedef T return_type;
|
||||
typedef T mutable_return_type;
|
||||
static const size_t element_stride = sizeof(T);
|
||||
|
||||
static return_type Read(const uint8_t *p, const size_t i) {
|
||||
return EndianScalar((reinterpret_cast<const T *>(p))[i]);
|
||||
static return_type Read(const uint8_t* p, const size_t i) {
|
||||
return EndianScalar((reinterpret_cast<const T*>(p))[i]);
|
||||
}
|
||||
static mutable_return_type Read(uint8_t *p, const size_t i) {
|
||||
static mutable_return_type Read(uint8_t* p, const size_t i) {
|
||||
return reinterpret_cast<mutable_return_type>(
|
||||
Read(const_cast<const uint8_t *>(p), i));
|
||||
Read(const_cast<const uint8_t*>(p), i));
|
||||
}
|
||||
};
|
||||
|
||||
// For vector of Offsets.
|
||||
template<typename T, template<typename> class OffsetT>
|
||||
template <typename T, template <typename> class OffsetT>
|
||||
struct IndirectHelper<OffsetT<T>> {
|
||||
typedef const T *return_type;
|
||||
typedef T *mutable_return_type;
|
||||
typedef const T* return_type;
|
||||
typedef T* mutable_return_type;
|
||||
typedef typename OffsetT<T>::offset_type offset_type;
|
||||
static const offset_type element_stride = sizeof(offset_type);
|
||||
|
||||
static return_type Read(const uint8_t *const p, const offset_type i) {
|
||||
static return_type Read(const uint8_t* const p, const offset_type i) {
|
||||
// Offsets are relative to themselves, so first update the pointer to
|
||||
// point to the offset location.
|
||||
const uint8_t *const offset_location = p + i * element_stride;
|
||||
const uint8_t* const offset_location = p + i * element_stride;
|
||||
|
||||
// Then read the scalar value of the offset (which may be 32 or 64-bits) and
|
||||
// then determine the relative location from the offset location.
|
||||
return reinterpret_cast<return_type>(
|
||||
offset_location + ReadScalar<offset_type>(offset_location));
|
||||
}
|
||||
static mutable_return_type Read(uint8_t *const p, const offset_type i) {
|
||||
static mutable_return_type Read(uint8_t* const p, const offset_type i) {
|
||||
// Offsets are relative to themselves, so first update the pointer to
|
||||
// point to the offset location.
|
||||
uint8_t *const offset_location = p + i * element_stride;
|
||||
uint8_t* const offset_location = p + i * element_stride;
|
||||
|
||||
// Then read the scalar value of the offset (which may be 32 or 64-bits) and
|
||||
// then determine the relative location from the offset location.
|
||||
@@ -135,16 +150,26 @@ struct IndirectHelper<OffsetT<T>> {
|
||||
};
|
||||
|
||||
// For vector of structs.
|
||||
template<typename T> struct IndirectHelper<const T *> {
|
||||
typedef const T *return_type;
|
||||
typedef T *mutable_return_type;
|
||||
static const size_t element_stride = sizeof(T);
|
||||
template <typename T>
|
||||
struct IndirectHelper<
|
||||
T, typename std::enable_if<
|
||||
!std::is_scalar<typename std::remove_pointer<T>::type>::value &&
|
||||
!is_specialisation_of_Offset<T>::value &&
|
||||
!is_specialisation_of_Offset64<T>::value>::type> {
|
||||
private:
|
||||
typedef typename std::remove_pointer<typename std::remove_cv<T>::type>::type
|
||||
pointee_type;
|
||||
|
||||
static return_type Read(const uint8_t *const p, const size_t i) {
|
||||
public:
|
||||
typedef const pointee_type* return_type;
|
||||
typedef pointee_type* mutable_return_type;
|
||||
static const size_t element_stride = sizeof(pointee_type);
|
||||
|
||||
static return_type Read(const uint8_t* const p, const size_t i) {
|
||||
// Structs are stored inline, relative to the first struct pointer.
|
||||
return reinterpret_cast<return_type>(p + i * element_stride);
|
||||
}
|
||||
static mutable_return_type Read(uint8_t *const p, const size_t i) {
|
||||
static mutable_return_type Read(uint8_t* const p, const size_t i) {
|
||||
// Structs are stored inline, relative to the first struct pointer.
|
||||
return reinterpret_cast<mutable_return_type>(p + i * element_stride);
|
||||
}
|
||||
@@ -157,14 +182,14 @@ template<typename T> struct IndirectHelper<const T *> {
|
||||
/// This function is UNDEFINED for FlatBuffers whose schema does not include
|
||||
/// a file_identifier (likely points at padding or the start of a the root
|
||||
/// vtable).
|
||||
inline const char *GetBufferIdentifier(const void *buf,
|
||||
inline const char* GetBufferIdentifier(const void* buf,
|
||||
bool size_prefixed = false) {
|
||||
return reinterpret_cast<const char *>(buf) +
|
||||
return reinterpret_cast<const char*>(buf) +
|
||||
((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
|
||||
}
|
||||
|
||||
// Helper to see if the identifier in a buffer has the expected value.
|
||||
inline bool BufferHasIdentifier(const void *buf, const char *identifier,
|
||||
inline bool BufferHasIdentifier(const void* buf, const char* identifier,
|
||||
bool size_prefixed = false) {
|
||||
return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
|
||||
flatbuffers::kFileIdentifierLength) == 0;
|
||||
@@ -172,26 +197,27 @@ inline bool BufferHasIdentifier(const void *buf, const char *identifier,
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
// Helpers to get a typed pointer to the root object contained in the buffer.
|
||||
template<typename T> T *GetMutableRoot(void *buf) {
|
||||
template <typename T>
|
||||
T* GetMutableRoot(void* buf) {
|
||||
if (!buf) return nullptr;
|
||||
EndianCheck();
|
||||
return reinterpret_cast<T *>(
|
||||
reinterpret_cast<uint8_t *>(buf) +
|
||||
EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
|
||||
return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(buf) +
|
||||
EndianScalar(*reinterpret_cast<uoffset_t*>(buf)));
|
||||
}
|
||||
|
||||
template<typename T, typename SizeT = uoffset_t>
|
||||
T *GetMutableSizePrefixedRoot(void *buf) {
|
||||
return GetMutableRoot<T>(reinterpret_cast<uint8_t *>(buf) + sizeof(SizeT));
|
||||
template <typename T, typename SizeT = uoffset_t>
|
||||
T* GetMutableSizePrefixedRoot(void* buf) {
|
||||
return GetMutableRoot<T>(reinterpret_cast<uint8_t*>(buf) + sizeof(SizeT));
|
||||
}
|
||||
|
||||
template<typename T> const T *GetRoot(const void *buf) {
|
||||
return GetMutableRoot<T>(const_cast<void *>(buf));
|
||||
template <typename T>
|
||||
const T* GetRoot(const void* buf) {
|
||||
return GetMutableRoot<T>(const_cast<void*>(buf));
|
||||
}
|
||||
|
||||
template<typename T, typename SizeT = uoffset_t>
|
||||
const T *GetSizePrefixedRoot(const void *buf) {
|
||||
return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(SizeT));
|
||||
template <typename T, typename SizeT = uoffset_t>
|
||||
const T* GetSizePrefixedRoot(const void* buf) {
|
||||
return GetRoot<T>(reinterpret_cast<const uint8_t*>(buf) + sizeof(SizeT));
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
+5
-4
@@ -27,23 +27,24 @@ namespace flatbuffers {
|
||||
// A BufferRef does not own its buffer.
|
||||
struct BufferRefBase {}; // for std::is_base_of
|
||||
|
||||
template<typename T> struct BufferRef : BufferRefBase {
|
||||
template <typename T>
|
||||
struct BufferRef : BufferRefBase {
|
||||
BufferRef() : buf(nullptr), len(0), must_free(false) {}
|
||||
BufferRef(uint8_t *_buf, uoffset_t _len)
|
||||
BufferRef(uint8_t* _buf, uoffset_t _len)
|
||||
: buf(_buf), len(_len), must_free(false) {}
|
||||
|
||||
~BufferRef() {
|
||||
if (must_free) free(buf);
|
||||
}
|
||||
|
||||
const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
|
||||
const T* GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
|
||||
|
||||
bool Verify() {
|
||||
Verifier verifier(buf, len);
|
||||
return verifier.VerifyBuffer<T>(nullptr);
|
||||
}
|
||||
|
||||
uint8_t *buf;
|
||||
uint8_t* buf;
|
||||
uoffset_t len;
|
||||
bool must_free;
|
||||
};
|
||||
|
||||
@@ -25,32 +25,32 @@ namespace flatbuffers {
|
||||
// DefaultAllocator uses new/delete to allocate memory regions
|
||||
class DefaultAllocator : public Allocator {
|
||||
public:
|
||||
uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE {
|
||||
uint8_t* allocate(size_t size) FLATBUFFERS_OVERRIDE {
|
||||
return new uint8_t[size];
|
||||
}
|
||||
|
||||
void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; }
|
||||
void deallocate(uint8_t* p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; }
|
||||
|
||||
static void dealloc(void *p, size_t) { delete[] static_cast<uint8_t *>(p); }
|
||||
static void dealloc(void* p, size_t) { delete[] static_cast<uint8_t*>(p); }
|
||||
};
|
||||
|
||||
// These functions allow for a null allocator to mean use the default allocator,
|
||||
// as used by DetachedBuffer and vector_downward below.
|
||||
// This is to avoid having a statically or dynamically allocated default
|
||||
// allocator, or having to move it between the classes that may own it.
|
||||
inline uint8_t *Allocate(Allocator *allocator, size_t size) {
|
||||
inline uint8_t* Allocate(Allocator* allocator, size_t size) {
|
||||
return allocator ? allocator->allocate(size)
|
||||
: DefaultAllocator().allocate(size);
|
||||
}
|
||||
|
||||
inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) {
|
||||
inline void Deallocate(Allocator* allocator, uint8_t* p, size_t size) {
|
||||
if (allocator)
|
||||
allocator->deallocate(p, size);
|
||||
else
|
||||
DefaultAllocator().deallocate(p, size);
|
||||
}
|
||||
|
||||
inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
|
||||
inline uint8_t* ReallocateDownward(Allocator* allocator, uint8_t* old_p,
|
||||
size_t old_size, size_t new_size,
|
||||
size_t in_use_back, size_t in_use_front) {
|
||||
return allocator ? allocator->reallocate_downward(old_p, old_size, new_size,
|
||||
|
||||
+19
-12
@@ -36,8 +36,8 @@ class DetachedBuffer {
|
||||
cur_(nullptr),
|
||||
size_(0) {}
|
||||
|
||||
DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf,
|
||||
size_t reserved, uint8_t *cur, size_t sz)
|
||||
DetachedBuffer(Allocator* allocator, bool own_allocator, uint8_t* buf,
|
||||
size_t reserved, uint8_t* cur, size_t sz)
|
||||
: allocator_(allocator),
|
||||
own_allocator_(own_allocator),
|
||||
buf_(buf),
|
||||
@@ -45,7 +45,7 @@ class DetachedBuffer {
|
||||
cur_(cur),
|
||||
size_(sz) {}
|
||||
|
||||
DetachedBuffer(DetachedBuffer &&other) noexcept
|
||||
DetachedBuffer(DetachedBuffer&& other) noexcept
|
||||
: allocator_(other.allocator_),
|
||||
own_allocator_(other.own_allocator_),
|
||||
buf_(other.buf_),
|
||||
@@ -55,7 +55,7 @@ class DetachedBuffer {
|
||||
other.reset();
|
||||
}
|
||||
|
||||
DetachedBuffer &operator=(DetachedBuffer &&other) noexcept {
|
||||
DetachedBuffer& operator=(DetachedBuffer&& other) noexcept {
|
||||
if (this == &other) return *this;
|
||||
|
||||
destroy();
|
||||
@@ -74,28 +74,35 @@ class DetachedBuffer {
|
||||
|
||||
~DetachedBuffer() { destroy(); }
|
||||
|
||||
const uint8_t *data() const { return cur_; }
|
||||
const uint8_t* data() const { return cur_; }
|
||||
|
||||
uint8_t *data() { return cur_; }
|
||||
uint8_t* data() { return cur_; }
|
||||
|
||||
size_t size() const { return size_; }
|
||||
|
||||
uint8_t* begin() { return data(); }
|
||||
const uint8_t* begin() const { return data(); }
|
||||
uint8_t* end() { return data() + size(); }
|
||||
const uint8_t* end() const { return data() + size(); }
|
||||
|
||||
// These may change access mode, leave these at end of public section
|
||||
FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other));
|
||||
FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer& other));
|
||||
FLATBUFFERS_DELETE_FUNC(
|
||||
DetachedBuffer &operator=(const DetachedBuffer &other));
|
||||
DetachedBuffer& operator=(const DetachedBuffer& other));
|
||||
|
||||
protected:
|
||||
Allocator *allocator_;
|
||||
Allocator* allocator_;
|
||||
bool own_allocator_;
|
||||
uint8_t *buf_;
|
||||
uint8_t* buf_;
|
||||
size_t reserved_;
|
||||
uint8_t *cur_;
|
||||
uint8_t* cur_;
|
||||
size_t size_;
|
||||
|
||||
inline void destroy() {
|
||||
if (buf_) Deallocate(allocator_, buf_, reserved_);
|
||||
if (own_allocator_ && allocator_) { delete allocator_; }
|
||||
if (own_allocator_ && allocator_) {
|
||||
delete allocator_;
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
+272
-236
File diff suppressed because it is too large
Load Diff
+41
-30
@@ -41,14 +41,14 @@ namespace flatbuffers {
|
||||
/// it is the opposite transformation of GetRoot().
|
||||
/// This may be useful if you want to pass on a root and have the recipient
|
||||
/// delete the buffer afterwards.
|
||||
inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
|
||||
auto table = reinterpret_cast<const Table *>(root);
|
||||
inline const uint8_t* GetBufferStartFromRootPointer(const void* root) {
|
||||
auto table = reinterpret_cast<const Table*>(root);
|
||||
auto vtable = table->GetVTable();
|
||||
// Either the vtable is before the root or after the root.
|
||||
auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root));
|
||||
auto start = (std::min)(vtable, reinterpret_cast<const uint8_t*>(root));
|
||||
// Align to at least sizeof(uoffset_t).
|
||||
start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) &
|
||||
~(sizeof(uoffset_t) - 1));
|
||||
start = reinterpret_cast<const uint8_t*>(reinterpret_cast<uintptr_t>(start) &
|
||||
~(sizeof(uoffset_t) - 1));
|
||||
// Additionally, there may be a file_identifier in the buffer, and the root
|
||||
// offset. The buffer may have been aligned to any size between
|
||||
// sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
|
||||
@@ -64,7 +64,7 @@ inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
|
||||
possible_roots; possible_roots--) {
|
||||
start -= sizeof(uoffset_t);
|
||||
if (ReadScalar<uoffset_t>(start) + start ==
|
||||
reinterpret_cast<const uint8_t *>(root))
|
||||
reinterpret_cast<const uint8_t*>(root))
|
||||
return start;
|
||||
}
|
||||
// We didn't find the root, either the "root" passed isn't really a root,
|
||||
@@ -76,11 +76,22 @@ inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
|
||||
}
|
||||
|
||||
/// @brief This return the prefixed size of a FlatBuffer.
|
||||
template<typename SizeT = uoffset_t>
|
||||
inline SizeT GetPrefixedSize(const uint8_t *buf) {
|
||||
template <typename SizeT = uoffset_t>
|
||||
inline SizeT GetPrefixedSize(const uint8_t* buf) {
|
||||
return ReadScalar<SizeT>(buf);
|
||||
}
|
||||
|
||||
// Gets the total length of the buffer given a sized prefixed FlatBuffer.
|
||||
//
|
||||
// This includes the size of the prefix as well as the buffer:
|
||||
//
|
||||
// [size prefix][flatbuffer]
|
||||
// |---------length--------|
|
||||
template <typename SizeT = uoffset_t>
|
||||
inline SizeT GetSizePrefixedBufferLength(const uint8_t* const buf) {
|
||||
return ReadScalar<SizeT>(buf) + sizeof(SizeT);
|
||||
}
|
||||
|
||||
// Base class for native objects (FlatBuffer data de-serialized into native
|
||||
// C++ data structures).
|
||||
// Contains no functionality, purely documentative.
|
||||
@@ -95,9 +106,9 @@ struct NativeTable {};
|
||||
/// if you wish. The resolver does the opposite lookup, for when the object
|
||||
/// is being serialized again.
|
||||
typedef uint64_t hash_value_t;
|
||||
typedef std::function<void(void **pointer_adr, hash_value_t hash)>
|
||||
typedef std::function<void(void** pointer_adr, hash_value_t hash)>
|
||||
resolver_function_t;
|
||||
typedef std::function<hash_value_t(void *pointer)> rehasher_function_t;
|
||||
typedef std::function<hash_value_t(void* pointer)> rehasher_function_t;
|
||||
|
||||
// Helper function to test if a field is present, using any of the field
|
||||
// enums in the generated code.
|
||||
@@ -106,18 +117,18 @@ typedef std::function<hash_value_t(void *pointer)> rehasher_function_t;
|
||||
// Note: this function will return false for fields equal to the default
|
||||
// value, since they're not stored in the buffer (unless force_defaults was
|
||||
// used).
|
||||
template<typename T>
|
||||
bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) {
|
||||
template <typename T>
|
||||
bool IsFieldPresent(const T* table, typename T::FlatBuffersVTableOffset field) {
|
||||
// Cast, since Table is a private baseclass of any table types.
|
||||
return reinterpret_cast<const Table *>(table)->CheckField(
|
||||
return reinterpret_cast<const Table*>(table)->CheckField(
|
||||
static_cast<voffset_t>(field));
|
||||
}
|
||||
|
||||
// Utility function for reverse lookups on the EnumNames*() functions
|
||||
// (in the generated C++ code)
|
||||
// names must be NULL terminated.
|
||||
inline int LookupEnum(const char **names, const char *name) {
|
||||
for (const char **p = names; *p; p++)
|
||||
inline int LookupEnum(const char** names, const char* name) {
|
||||
for (const char** p = names; *p; p++)
|
||||
if (!strcmp(*p, name)) return static_cast<int>(p - names);
|
||||
return -1;
|
||||
}
|
||||
@@ -216,20 +227,20 @@ static_assert(sizeof(TypeCode) == 2, "TypeCode");
|
||||
struct TypeTable;
|
||||
|
||||
// Signature of the static method present in each type.
|
||||
typedef const TypeTable *(*TypeFunction)();
|
||||
typedef const TypeTable* (*TypeFunction)();
|
||||
|
||||
struct TypeTable {
|
||||
SequenceType st;
|
||||
size_t num_elems; // of type_codes, values, names (but not type_refs).
|
||||
const TypeCode *type_codes; // num_elems count
|
||||
const TypeFunction *type_refs; // less than num_elems entries (see TypeCode).
|
||||
const int16_t *array_sizes; // less than num_elems entries (see TypeCode).
|
||||
const int64_t *values; // Only set for non-consecutive enum/union or structs.
|
||||
const char *const *names; // Only set if compiled with --reflect-names.
|
||||
const TypeCode* type_codes; // num_elems count
|
||||
const TypeFunction* type_refs; // less than num_elems entries (see TypeCode).
|
||||
const int16_t* array_sizes; // less than num_elems entries (see TypeCode).
|
||||
const int64_t* values; // Only set for non-consecutive enum/union or structs.
|
||||
const char* const* names; // Only set if compiled with --reflect-names.
|
||||
};
|
||||
|
||||
// String which identifies the current version of FlatBuffers.
|
||||
inline const char *flatbuffers_version_string() {
|
||||
inline const char* flatbuffers_version_string() {
|
||||
return "FlatBuffers " FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
|
||||
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
|
||||
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
|
||||
@@ -237,31 +248,31 @@ inline const char *flatbuffers_version_string() {
|
||||
|
||||
// clang-format off
|
||||
#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
|
||||
inline E operator | (E lhs, E rhs){\
|
||||
inline FLATBUFFERS_CONSTEXPR_CPP11 E operator | (E lhs, E rhs){\
|
||||
return E(T(lhs) | T(rhs));\
|
||||
}\
|
||||
inline E operator & (E lhs, E rhs){\
|
||||
inline FLATBUFFERS_CONSTEXPR_CPP11 E operator & (E lhs, E rhs){\
|
||||
return E(T(lhs) & T(rhs));\
|
||||
}\
|
||||
inline E operator ^ (E lhs, E rhs){\
|
||||
inline FLATBUFFERS_CONSTEXPR_CPP11 E operator ^ (E lhs, E rhs){\
|
||||
return E(T(lhs) ^ T(rhs));\
|
||||
}\
|
||||
inline E operator ~ (E lhs){\
|
||||
inline FLATBUFFERS_CONSTEXPR_CPP11 E operator ~ (E lhs){\
|
||||
return E(~T(lhs));\
|
||||
}\
|
||||
inline E operator |= (E &lhs, E rhs){\
|
||||
inline FLATBUFFERS_CONSTEXPR_CPP11 E operator |= (E &lhs, E rhs){\
|
||||
lhs = lhs | rhs;\
|
||||
return lhs;\
|
||||
}\
|
||||
inline E operator &= (E &lhs, E rhs){\
|
||||
inline FLATBUFFERS_CONSTEXPR_CPP11 E operator &= (E &lhs, E rhs){\
|
||||
lhs = lhs & rhs;\
|
||||
return lhs;\
|
||||
}\
|
||||
inline E operator ^= (E &lhs, E rhs){\
|
||||
inline FLATBUFFERS_CONSTEXPR_CPP11 E operator ^= (E &lhs, E rhs){\
|
||||
lhs = lhs ^ rhs;\
|
||||
return lhs;\
|
||||
}\
|
||||
inline bool operator !(E rhs) \
|
||||
inline FLATBUFFERS_CONSTEXPR_CPP11 bool operator !(E rhs) \
|
||||
{\
|
||||
return !bool(T(rhs)); \
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@
|
||||
// Testing __cpp_lib_span requires including either <version> or <span>,
|
||||
// both of which were added in C++20.
|
||||
// See: https://en.cppreference.com/w/cpp/utility/feature_test
|
||||
#if defined(__cplusplus) && __cplusplus >= 202002L
|
||||
#if defined(__cplusplus) && __cplusplus >= 202002L \
|
||||
|| (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
#define FLATBUFFERS_USE_STD_SPAN 1
|
||||
#endif
|
||||
#endif // FLATBUFFERS_USE_STD_SPAN
|
||||
@@ -272,7 +273,7 @@ template<class T, class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
|
||||
return static_cast<bool>(lhs) != static_cast<bool>(rhs)
|
||||
? false
|
||||
: !static_cast<bool>(lhs) ? false : (*lhs == *rhs);
|
||||
: !static_cast<bool>(lhs) ? true : (*lhs == *rhs);
|
||||
}
|
||||
#endif // FLATBUFFERS_USE_STD_OPTIONAL
|
||||
|
||||
|
||||
+10
-5
@@ -23,7 +23,7 @@
|
||||
namespace flatbuffers {
|
||||
|
||||
struct String : public Vector<char> {
|
||||
const char *c_str() const { return reinterpret_cast<const char *>(Data()); }
|
||||
const char* c_str() const { return reinterpret_cast<const char*>(Data()); }
|
||||
std::string str() const { return std::string(c_str(), size()); }
|
||||
|
||||
// clang-format off
|
||||
@@ -31,30 +31,35 @@ struct String : public Vector<char> {
|
||||
flatbuffers::string_view string_view() const {
|
||||
return flatbuffers::string_view(c_str(), size());
|
||||
}
|
||||
|
||||
/* implicit */
|
||||
operator flatbuffers::string_view() const {
|
||||
return flatbuffers::string_view(c_str(), size());
|
||||
}
|
||||
#endif // FLATBUFFERS_HAS_STRING_VIEW
|
||||
// clang-format on
|
||||
|
||||
bool operator<(const String &o) const {
|
||||
bool operator<(const String& o) const {
|
||||
return StringLessThan(this->data(), this->size(), o.data(), o.size());
|
||||
}
|
||||
};
|
||||
|
||||
// Convenience function to get std::string from a String returning an empty
|
||||
// string on null pointer.
|
||||
static inline std::string GetString(const String *str) {
|
||||
static inline std::string GetString(const String* str) {
|
||||
return str ? str->str() : "";
|
||||
}
|
||||
|
||||
// Convenience function to get char* from a String returning an empty string on
|
||||
// null pointer.
|
||||
static inline const char *GetCstring(const String *str) {
|
||||
static inline const char* GetCstring(const String* str) {
|
||||
return str ? str->c_str() : "";
|
||||
}
|
||||
|
||||
#ifdef FLATBUFFERS_HAS_STRING_VIEW
|
||||
// Convenience function to get string_view from a String returning an empty
|
||||
// string_view on null pointer.
|
||||
static inline flatbuffers::string_view GetStringView(const String *str) {
|
||||
static inline flatbuffers::string_view GetStringView(const String* str) {
|
||||
return str ? str->string_view() : flatbuffers::string_view();
|
||||
}
|
||||
#endif // FLATBUFFERS_HAS_STRING_VIEW
|
||||
|
||||
+8
-6
@@ -27,23 +27,25 @@ namespace flatbuffers {
|
||||
|
||||
class Struct FLATBUFFERS_FINAL_CLASS {
|
||||
public:
|
||||
template<typename T> T GetField(uoffset_t o) const {
|
||||
template <typename T>
|
||||
T GetField(uoffset_t o) const {
|
||||
return ReadScalar<T>(&data_[o]);
|
||||
}
|
||||
|
||||
template<typename T> T GetStruct(uoffset_t o) const {
|
||||
template <typename T>
|
||||
T GetStruct(uoffset_t o) const {
|
||||
return reinterpret_cast<T>(&data_[o]);
|
||||
}
|
||||
|
||||
const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
|
||||
uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
|
||||
const uint8_t* GetAddressOf(uoffset_t o) const { return &data_[o]; }
|
||||
uint8_t* GetAddressOf(uoffset_t o) { return &data_[o]; }
|
||||
|
||||
private:
|
||||
// private constructor & copy constructor: you obtain instances of this
|
||||
// class by pointing to existing data only
|
||||
Struct();
|
||||
Struct(const Struct &);
|
||||
Struct &operator=(const Struct &);
|
||||
Struct(const Struct&);
|
||||
Struct& operator=(const Struct&);
|
||||
|
||||
uint8_t data_[1];
|
||||
};
|
||||
|
||||
+37
-31
@@ -26,7 +26,7 @@ namespace flatbuffers {
|
||||
// omitted and added at will, but uses an extra indirection to read.
|
||||
class Table {
|
||||
public:
|
||||
const uint8_t *GetVTable() const {
|
||||
const uint8_t* GetVTable() const {
|
||||
return data_ - ReadScalar<soffset_t>(data_);
|
||||
}
|
||||
|
||||
@@ -42,38 +42,42 @@ class Table {
|
||||
return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
|
||||
}
|
||||
|
||||
template<typename T> T GetField(voffset_t field, T defaultval) const {
|
||||
template <typename T>
|
||||
T GetField(voffset_t field, T defaultval) const {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
|
||||
}
|
||||
|
||||
template<typename P, typename OffsetSize = uoffset_t>
|
||||
template <typename P, typename OffsetSize = uoffset_t>
|
||||
P GetPointer(voffset_t field) {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
auto p = data_ + field_offset;
|
||||
return field_offset ? reinterpret_cast<P>(p + ReadScalar<OffsetSize>(p))
|
||||
: nullptr;
|
||||
}
|
||||
template<typename P, typename OffsetSize = uoffset_t>
|
||||
template <typename P, typename OffsetSize = uoffset_t>
|
||||
P GetPointer(voffset_t field) const {
|
||||
return const_cast<Table *>(this)->GetPointer<P, OffsetSize>(field);
|
||||
return const_cast<Table*>(this)->GetPointer<P, OffsetSize>(field);
|
||||
}
|
||||
|
||||
template<typename P> P GetPointer64(voffset_t field) {
|
||||
template <typename P>
|
||||
P GetPointer64(voffset_t field) {
|
||||
return GetPointer<P, uoffset64_t>(field);
|
||||
}
|
||||
|
||||
template<typename P> P GetPointer64(voffset_t field) const {
|
||||
template <typename P>
|
||||
P GetPointer64(voffset_t field) const {
|
||||
return GetPointer<P, uoffset64_t>(field);
|
||||
}
|
||||
|
||||
template<typename P> P GetStruct(voffset_t field) const {
|
||||
template <typename P>
|
||||
P GetStruct(voffset_t field) const {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
auto p = const_cast<uint8_t *>(data_ + field_offset);
|
||||
auto p = const_cast<uint8_t*>(data_ + field_offset);
|
||||
return field_offset ? reinterpret_cast<P>(p) : nullptr;
|
||||
}
|
||||
|
||||
template<typename Raw, typename Face>
|
||||
template <typename Raw, typename Face>
|
||||
flatbuffers::Optional<Face> GetOptional(voffset_t field) const {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
auto p = data_ + field_offset;
|
||||
@@ -81,20 +85,22 @@ class Table {
|
||||
: Optional<Face>();
|
||||
}
|
||||
|
||||
template<typename T> bool SetField(voffset_t field, T val, T def) {
|
||||
template <typename T>
|
||||
bool SetField(voffset_t field, T val, T def) {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
if (!field_offset) return IsTheSameAs(val, def);
|
||||
WriteScalar(data_ + field_offset, val);
|
||||
return true;
|
||||
}
|
||||
template<typename T> bool SetField(voffset_t field, T val) {
|
||||
template <typename T>
|
||||
bool SetField(voffset_t field, T val) {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
if (!field_offset) return false;
|
||||
WriteScalar(data_ + field_offset, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetPointer(voffset_t field, const uint8_t *val) {
|
||||
bool SetPointer(voffset_t field, const uint8_t* val) {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
if (!field_offset) return false;
|
||||
WriteScalar(data_ + field_offset,
|
||||
@@ -102,12 +108,12 @@ class Table {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t *GetAddressOf(voffset_t field) {
|
||||
uint8_t* GetAddressOf(voffset_t field) {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
return field_offset ? data_ + field_offset : nullptr;
|
||||
}
|
||||
const uint8_t *GetAddressOf(voffset_t field) const {
|
||||
return const_cast<Table *>(this)->GetAddressOf(field);
|
||||
const uint8_t* GetAddressOf(voffset_t field) const {
|
||||
return const_cast<Table*>(this)->GetAddressOf(field);
|
||||
}
|
||||
|
||||
bool CheckField(voffset_t field) const {
|
||||
@@ -116,13 +122,13 @@ class Table {
|
||||
|
||||
// Verify the vtable of this table.
|
||||
// Call this once per table, followed by VerifyField once per field.
|
||||
bool VerifyTableStart(Verifier &verifier) const {
|
||||
bool VerifyTableStart(Verifier& verifier) const {
|
||||
return verifier.VerifyTableStart(data_);
|
||||
}
|
||||
|
||||
// Verify a particular field.
|
||||
template<typename T>
|
||||
bool VerifyField(const Verifier &verifier, voffset_t field,
|
||||
template <typename T>
|
||||
bool VerifyField(const Verifier& verifier, voffset_t field,
|
||||
size_t align) const {
|
||||
// Calling GetOptionalFieldOffset should be safe now thanks to
|
||||
// VerifyTable().
|
||||
@@ -132,8 +138,8 @@ class Table {
|
||||
}
|
||||
|
||||
// VerifyField for required fields.
|
||||
template<typename T>
|
||||
bool VerifyFieldRequired(const Verifier &verifier, voffset_t field,
|
||||
template <typename T>
|
||||
bool VerifyFieldRequired(const Verifier& verifier, voffset_t field,
|
||||
size_t align) const {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
return verifier.Check(field_offset != 0) &&
|
||||
@@ -141,24 +147,24 @@ class Table {
|
||||
}
|
||||
|
||||
// Versions for offsets.
|
||||
template<typename OffsetT = uoffset_t>
|
||||
bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
|
||||
template <typename OffsetT = uoffset_t>
|
||||
bool VerifyOffset(const Verifier& verifier, voffset_t field) const {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
return !field_offset || verifier.VerifyOffset<OffsetT>(data_, field_offset);
|
||||
}
|
||||
|
||||
template<typename OffsetT = uoffset_t>
|
||||
bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
|
||||
template <typename OffsetT = uoffset_t>
|
||||
bool VerifyOffsetRequired(const Verifier& verifier, voffset_t field) const {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
return verifier.Check(field_offset != 0) &&
|
||||
verifier.VerifyOffset<OffsetT>(data_, field_offset);
|
||||
}
|
||||
|
||||
bool VerifyOffset64(const Verifier &verifier, voffset_t field) const {
|
||||
|
||||
bool VerifyOffset64(const Verifier& verifier, voffset_t field) const {
|
||||
return VerifyOffset<uoffset64_t>(verifier, field);
|
||||
}
|
||||
|
||||
bool VerifyOffset64Required(const Verifier &verifier, voffset_t field) const {
|
||||
bool VerifyOffset64Required(const Verifier& verifier, voffset_t field) const {
|
||||
return VerifyOffsetRequired<uoffset64_t>(verifier, field);
|
||||
}
|
||||
|
||||
@@ -166,15 +172,15 @@ class Table {
|
||||
// private constructor & copy constructor: you obtain instances of this
|
||||
// class by pointing to existing data only
|
||||
Table();
|
||||
Table(const Table &other);
|
||||
Table &operator=(const Table &);
|
||||
Table(const Table& other);
|
||||
Table& operator=(const Table&);
|
||||
|
||||
uint8_t data_[1];
|
||||
};
|
||||
|
||||
// This specialization allows avoiding warnings like:
|
||||
// MSVC C4800: type: forcing value to bool 'true' or 'false'.
|
||||
template<>
|
||||
template <>
|
||||
inline flatbuffers::Optional<bool> Table::GetOptional<uint8_t, bool>(
|
||||
voffset_t field) const {
|
||||
auto field_offset = GetOptionalFieldOffset(field);
|
||||
|
||||
+101
-79
@@ -27,44 +27,56 @@ struct String;
|
||||
|
||||
// An STL compatible iterator implementation for Vector below, effectively
|
||||
// calling Get() for every element.
|
||||
template<typename T, typename IT, typename Data = uint8_t *,
|
||||
typename SizeT = uoffset_t>
|
||||
template <typename T, typename IT, typename Data = uint8_t*,
|
||||
typename SizeT = uoffset_t>
|
||||
struct VectorIterator {
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
typedef IT value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef IT *pointer;
|
||||
typedef IT &reference;
|
||||
typedef IT* pointer;
|
||||
typedef IT& reference;
|
||||
|
||||
static const SizeT element_stride = IndirectHelper<T>::element_stride;
|
||||
|
||||
VectorIterator(Data data, SizeT i) : data_(data + element_stride * i) {}
|
||||
VectorIterator(const VectorIterator &other) : data_(other.data_) {}
|
||||
VectorIterator(const VectorIterator& other) : data_(other.data_) {}
|
||||
VectorIterator() : data_(nullptr) {}
|
||||
|
||||
VectorIterator &operator=(const VectorIterator &other) {
|
||||
VectorIterator& operator=(const VectorIterator& other) {
|
||||
data_ = other.data_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VectorIterator &operator=(VectorIterator &&other) {
|
||||
VectorIterator& operator=(VectorIterator&& other) {
|
||||
data_ = other.data_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const VectorIterator &other) const {
|
||||
bool operator==(const VectorIterator& other) const {
|
||||
return data_ == other.data_;
|
||||
}
|
||||
|
||||
bool operator<(const VectorIterator &other) const {
|
||||
return data_ < other.data_;
|
||||
}
|
||||
|
||||
bool operator!=(const VectorIterator &other) const {
|
||||
bool operator!=(const VectorIterator& other) const {
|
||||
return data_ != other.data_;
|
||||
}
|
||||
|
||||
difference_type operator-(const VectorIterator &other) const {
|
||||
bool operator<(const VectorIterator& other) const {
|
||||
return data_ < other.data_;
|
||||
}
|
||||
|
||||
bool operator>(const VectorIterator& other) const {
|
||||
return data_ > other.data_;
|
||||
}
|
||||
|
||||
bool operator<=(const VectorIterator& other) const {
|
||||
return !(data_ > other.data_);
|
||||
}
|
||||
|
||||
bool operator>=(const VectorIterator& other) const {
|
||||
return !(data_ < other.data_);
|
||||
}
|
||||
|
||||
difference_type operator-(const VectorIterator& other) const {
|
||||
return (data_ - other.data_) / element_stride;
|
||||
}
|
||||
|
||||
@@ -76,7 +88,7 @@ struct VectorIterator {
|
||||
// `pointer operator->()`.
|
||||
IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
|
||||
|
||||
VectorIterator &operator++() {
|
||||
VectorIterator& operator++() {
|
||||
data_ += element_stride;
|
||||
return *this;
|
||||
}
|
||||
@@ -87,16 +99,16 @@ struct VectorIterator {
|
||||
return temp;
|
||||
}
|
||||
|
||||
VectorIterator operator+(const SizeT &offset) const {
|
||||
VectorIterator operator+(const SizeT& offset) const {
|
||||
return VectorIterator(data_ + offset * element_stride, 0);
|
||||
}
|
||||
|
||||
VectorIterator &operator+=(const SizeT &offset) {
|
||||
VectorIterator& operator+=(const SizeT& offset) {
|
||||
data_ += offset * element_stride;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VectorIterator &operator--() {
|
||||
VectorIterator& operator--() {
|
||||
data_ -= element_stride;
|
||||
return *this;
|
||||
}
|
||||
@@ -107,11 +119,11 @@ struct VectorIterator {
|
||||
return temp;
|
||||
}
|
||||
|
||||
VectorIterator operator-(const SizeT &offset) const {
|
||||
VectorIterator operator-(const SizeT& offset) const {
|
||||
return VectorIterator(data_ - offset * element_stride, 0);
|
||||
}
|
||||
|
||||
VectorIterator &operator-=(const SizeT &offset) {
|
||||
VectorIterator& operator-=(const SizeT& offset) {
|
||||
data_ -= offset * element_stride;
|
||||
return *this;
|
||||
}
|
||||
@@ -120,10 +132,10 @@ struct VectorIterator {
|
||||
Data data_;
|
||||
};
|
||||
|
||||
template<typename T, typename IT, typename SizeT = uoffset_t>
|
||||
using VectorConstIterator = VectorIterator<T, IT, const uint8_t *, SizeT>;
|
||||
template <typename T, typename IT, typename SizeT = uoffset_t>
|
||||
using VectorConstIterator = VectorIterator<T, IT, const uint8_t*, SizeT>;
|
||||
|
||||
template<typename Iterator>
|
||||
template <typename Iterator>
|
||||
struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
|
||||
explicit VectorReverseIterator(Iterator iter)
|
||||
: std::reverse_iterator<Iterator>(iter) {}
|
||||
@@ -145,14 +157,13 @@ struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
|
||||
|
||||
// This is used as a helper type for accessing vectors.
|
||||
// Vector::data() assumes the vector elements start after the length field.
|
||||
template<typename T, typename SizeT = uoffset_t> class Vector {
|
||||
template <typename T, typename SizeT = uoffset_t>
|
||||
class Vector {
|
||||
public:
|
||||
typedef VectorIterator<T,
|
||||
typename IndirectHelper<T>::mutable_return_type,
|
||||
uint8_t *, SizeT>
|
||||
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type,
|
||||
uint8_t*, SizeT>
|
||||
iterator;
|
||||
typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type,
|
||||
SizeT>
|
||||
typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type, SizeT>
|
||||
const_iterator;
|
||||
typedef VectorReverseIterator<iterator> reverse_iterator;
|
||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||
@@ -165,14 +176,18 @@ template<typename T, typename SizeT = uoffset_t> class Vector {
|
||||
|
||||
SizeT size() const { return EndianScalar(length_); }
|
||||
|
||||
// Returns true if the vector is empty.
|
||||
//
|
||||
// This just provides another standardized method that is expected of vectors.
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
// Deprecated: use size(). Here for backwards compatibility.
|
||||
FLATBUFFERS_ATTRIBUTE([[deprecated("use size() instead")]])
|
||||
SizeT Length() const { return size(); }
|
||||
|
||||
typedef SizeT size_type;
|
||||
typedef typename IndirectHelper<T>::return_type return_type;
|
||||
typedef typename IndirectHelper<T>::mutable_return_type
|
||||
mutable_return_type;
|
||||
typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
|
||||
typedef return_type value_type;
|
||||
|
||||
return_type Get(SizeT i) const {
|
||||
@@ -185,24 +200,26 @@ template<typename T, typename SizeT = uoffset_t> class Vector {
|
||||
// If this is a Vector of enums, T will be its storage type, not the enum
|
||||
// type. This function makes it convenient to retrieve value with enum
|
||||
// type E.
|
||||
template<typename E> E GetEnum(SizeT i) const {
|
||||
template <typename E>
|
||||
E GetEnum(SizeT i) const {
|
||||
return static_cast<E>(Get(i));
|
||||
}
|
||||
|
||||
// If this a vector of unions, this does the cast for you. There's no check
|
||||
// to make sure this is the right type!
|
||||
template<typename U> const U *GetAs(SizeT i) const {
|
||||
return reinterpret_cast<const U *>(Get(i));
|
||||
template <typename U>
|
||||
const U* GetAs(SizeT i) const {
|
||||
return reinterpret_cast<const U*>(Get(i));
|
||||
}
|
||||
|
||||
// If this a vector of unions, this does the cast for you. There's no check
|
||||
// to make sure this is actually a string!
|
||||
const String *GetAsString(SizeT i) const {
|
||||
return reinterpret_cast<const String *>(Get(i));
|
||||
const String* GetAsString(SizeT i) const {
|
||||
return reinterpret_cast<const String*>(Get(i));
|
||||
}
|
||||
|
||||
const void *GetStructFromOffset(size_t o) const {
|
||||
return reinterpret_cast<const void *>(Data() + o);
|
||||
const void* GetStructFromOffset(size_t o) const {
|
||||
return reinterpret_cast<const void*>(Data() + o);
|
||||
}
|
||||
|
||||
iterator begin() { return iterator(Data(), 0); }
|
||||
@@ -231,7 +248,7 @@ template<typename T, typename SizeT = uoffset_t> class Vector {
|
||||
|
||||
// Change elements if you have a non-const pointer to this object.
|
||||
// Scalars only. See reflection.h, and the documentation.
|
||||
void Mutate(SizeT i, const T &val) {
|
||||
void Mutate(SizeT i, const T& val) {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
WriteScalar(data() + i, val);
|
||||
}
|
||||
@@ -239,7 +256,7 @@ template<typename T, typename SizeT = uoffset_t> class Vector {
|
||||
// Change an element of a vector of tables (or strings).
|
||||
// "val" points to the new table/string, as you can obtain from
|
||||
// e.g. reflection::AddFlatBuffer().
|
||||
void MutateOffset(SizeT i, const uint8_t *val) {
|
||||
void MutateOffset(SizeT i, const uint8_t* val) {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
static_assert(sizeof(T) == sizeof(SizeT), "Unrelated types");
|
||||
WriteScalar(data() + i,
|
||||
@@ -253,30 +270,32 @@ template<typename T, typename SizeT = uoffset_t> class Vector {
|
||||
}
|
||||
|
||||
// The raw data in little endian format. Use with care.
|
||||
const uint8_t *Data() const {
|
||||
return reinterpret_cast<const uint8_t *>(&length_ + 1);
|
||||
const uint8_t* Data() const {
|
||||
return reinterpret_cast<const uint8_t*>(&length_ + 1);
|
||||
}
|
||||
|
||||
uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
|
||||
uint8_t* Data() { return reinterpret_cast<uint8_t*>(&length_ + 1); }
|
||||
|
||||
// Similarly, but typed, much like std::vector::data
|
||||
const T *data() const { return reinterpret_cast<const T *>(Data()); }
|
||||
T *data() { return reinterpret_cast<T *>(Data()); }
|
||||
const T* data() const { return reinterpret_cast<const T*>(Data()); }
|
||||
T* data() { return reinterpret_cast<T*>(Data()); }
|
||||
|
||||
template<typename K> return_type LookupByKey(K key) const {
|
||||
void *search_result = std::bsearch(
|
||||
template <typename K>
|
||||
return_type LookupByKey(K key) const {
|
||||
void* search_result = std::bsearch(
|
||||
&key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
|
||||
|
||||
if (!search_result) {
|
||||
return nullptr; // Key not found.
|
||||
}
|
||||
|
||||
const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
|
||||
const uint8_t* element = reinterpret_cast<const uint8_t*>(search_result);
|
||||
|
||||
return IndirectHelper<T>::Read(element, 0);
|
||||
}
|
||||
|
||||
template<typename K> mutable_return_type MutableLookupByKey(K key) {
|
||||
template <typename K>
|
||||
mutable_return_type MutableLookupByKey(K key) {
|
||||
return const_cast<mutable_return_type>(LookupByKey(key));
|
||||
}
|
||||
|
||||
@@ -290,12 +309,13 @@ template<typename T, typename SizeT = uoffset_t> class Vector {
|
||||
private:
|
||||
// This class is a pointer. Copying will therefore create an invalid object.
|
||||
// Private and unimplemented copy constructor.
|
||||
Vector(const Vector &);
|
||||
Vector &operator=(const Vector &);
|
||||
Vector(const Vector&);
|
||||
Vector& operator=(const Vector&);
|
||||
|
||||
template<typename K> static int KeyCompare(const void *ap, const void *bp) {
|
||||
const K *key = reinterpret_cast<const K *>(ap);
|
||||
const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
|
||||
template <typename K>
|
||||
static int KeyCompare(const void* ap, const void* bp) {
|
||||
const K* key = reinterpret_cast<const K*>(ap);
|
||||
const uint8_t* data = reinterpret_cast<const uint8_t*>(bp);
|
||||
auto table = IndirectHelper<T>::Read(data, 0);
|
||||
|
||||
// std::bsearch compares with the operands transposed, so we negate the
|
||||
@@ -304,35 +324,36 @@ template<typename T, typename SizeT = uoffset_t> class Vector {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> using Vector64 = Vector<T, uoffset64_t>;
|
||||
template <typename T>
|
||||
using Vector64 = Vector<T, uoffset64_t>;
|
||||
|
||||
template<class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> &vec)
|
||||
template <class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U>& vec)
|
||||
FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Vector<U>::is_span_observable,
|
||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
||||
return span<U>(vec.data(), vec.size());
|
||||
}
|
||||
|
||||
template<class U>
|
||||
template <class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
|
||||
const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
|
||||
const Vector<U>& vec) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Vector<U>::is_span_observable,
|
||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
||||
return span<const U>(vec.data(), vec.size());
|
||||
}
|
||||
|
||||
template<class U>
|
||||
template <class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t> make_bytes_span(
|
||||
Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
|
||||
Vector<U>& vec) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Vector<U>::scalar_tag::value,
|
||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
||||
return span<uint8_t>(vec.Data(), vec.size() * sizeof(U));
|
||||
}
|
||||
|
||||
template<class U>
|
||||
template <class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t> make_bytes_span(
|
||||
const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
|
||||
const Vector<U>& vec) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Vector<U>::scalar_tag::value,
|
||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
||||
return span<const uint8_t>(vec.Data(), vec.size() * sizeof(U));
|
||||
@@ -340,17 +361,17 @@ FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t> make_bytes_span(
|
||||
|
||||
// Convenient helper functions to get a span of any vector, regardless
|
||||
// of whether it is null or not (the field is not set).
|
||||
template<class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> *ptr)
|
||||
template <class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U>* ptr)
|
||||
FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Vector<U>::is_span_observable,
|
||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
||||
return ptr ? make_span(*ptr) : span<U>();
|
||||
}
|
||||
|
||||
template<class U>
|
||||
template <class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
|
||||
const Vector<U> *ptr) FLATBUFFERS_NOEXCEPT {
|
||||
const Vector<U>* ptr) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Vector<U>::is_span_observable,
|
||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
||||
return ptr ? make_span(*ptr) : span<const U>();
|
||||
@@ -362,10 +383,10 @@ class VectorOfAny {
|
||||
public:
|
||||
uoffset_t size() const { return EndianScalar(length_); }
|
||||
|
||||
const uint8_t *Data() const {
|
||||
return reinterpret_cast<const uint8_t *>(&length_ + 1);
|
||||
const uint8_t* Data() const {
|
||||
return reinterpret_cast<const uint8_t*>(&length_ + 1);
|
||||
}
|
||||
uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
|
||||
uint8_t* Data() { return reinterpret_cast<uint8_t*>(&length_ + 1); }
|
||||
|
||||
protected:
|
||||
VectorOfAny();
|
||||
@@ -373,25 +394,26 @@ class VectorOfAny {
|
||||
uoffset_t length_;
|
||||
|
||||
private:
|
||||
VectorOfAny(const VectorOfAny &);
|
||||
VectorOfAny &operator=(const VectorOfAny &);
|
||||
VectorOfAny(const VectorOfAny&);
|
||||
VectorOfAny& operator=(const VectorOfAny&);
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
|
||||
template <typename T, typename U>
|
||||
Vector<Offset<T>>* VectorCast(Vector<Offset<U>>* ptr) {
|
||||
static_assert(std::is_base_of<T, U>::value, "Unrelated types");
|
||||
return reinterpret_cast<Vector<Offset<T>> *>(ptr);
|
||||
return reinterpret_cast<Vector<Offset<T>>*>(ptr);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
|
||||
template <typename T, typename U>
|
||||
const Vector<Offset<T>>* VectorCast(const Vector<Offset<U>>* ptr) {
|
||||
static_assert(std::is_base_of<T, U>::value, "Unrelated types");
|
||||
return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
|
||||
return reinterpret_cast<const Vector<Offset<T>>*>(ptr);
|
||||
}
|
||||
|
||||
// Convenient helper function to get the length of any vector, regardless
|
||||
// of whether it is null or not (the field is not set).
|
||||
template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
|
||||
template <typename T>
|
||||
static inline size_t VectorLength(const Vector<T>* v) {
|
||||
return v ? v->size() : 0;
|
||||
}
|
||||
|
||||
|
||||
+41
-31
@@ -17,9 +17,8 @@
|
||||
#ifndef FLATBUFFERS_VECTOR_DOWNWARD_H_
|
||||
#define FLATBUFFERS_VECTOR_DOWNWARD_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
#include "flatbuffers/default_allocator.h"
|
||||
@@ -33,9 +32,10 @@ namespace flatbuffers {
|
||||
// Since this vector leaves the lower part unused, we support a "scratch-pad"
|
||||
// that can be stored there for temporary data, to share the allocated space.
|
||||
// Essentially, this supports 2 std::vectors in a single buffer.
|
||||
template<typename SizeT = uoffset_t> class vector_downward {
|
||||
template <typename SizeT = uoffset_t>
|
||||
class vector_downward {
|
||||
public:
|
||||
explicit vector_downward(size_t initial_size, Allocator *allocator,
|
||||
explicit vector_downward(size_t initial_size, Allocator* allocator,
|
||||
bool own_allocator, size_t buffer_minalign,
|
||||
const SizeT max_size = FLATBUFFERS_MAX_BUFFER_SIZE)
|
||||
: allocator_(allocator),
|
||||
@@ -49,7 +49,7 @@ template<typename SizeT = uoffset_t> class vector_downward {
|
||||
cur_(nullptr),
|
||||
scratch_(nullptr) {}
|
||||
|
||||
vector_downward(vector_downward &&other) noexcept
|
||||
vector_downward(vector_downward&& other) noexcept
|
||||
// clang-format on
|
||||
: allocator_(other.allocator_),
|
||||
own_allocator_(other.own_allocator_),
|
||||
@@ -71,7 +71,7 @@ template<typename SizeT = uoffset_t> class vector_downward {
|
||||
other.scratch_ = nullptr;
|
||||
}
|
||||
|
||||
vector_downward &operator=(vector_downward &&other) noexcept {
|
||||
vector_downward& operator=(vector_downward&& other) noexcept {
|
||||
// Move construct a temporary and swap idiom
|
||||
vector_downward temp(std::move(other));
|
||||
swap(temp);
|
||||
@@ -102,7 +102,9 @@ template<typename SizeT = uoffset_t> class vector_downward {
|
||||
void clear_scratch() { scratch_ = buf_; }
|
||||
|
||||
void clear_allocator() {
|
||||
if (own_allocator_ && allocator_) { delete allocator_; }
|
||||
if (own_allocator_ && allocator_) {
|
||||
delete allocator_;
|
||||
}
|
||||
allocator_ = nullptr;
|
||||
own_allocator_ = false;
|
||||
}
|
||||
@@ -113,8 +115,8 @@ template<typename SizeT = uoffset_t> class vector_downward {
|
||||
}
|
||||
|
||||
// Relinquish the pointer to the caller.
|
||||
uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) {
|
||||
auto *buf = buf_;
|
||||
uint8_t* release_raw(size_t& allocated_bytes, size_t& offset) {
|
||||
auto* buf = buf_;
|
||||
allocated_bytes = reserved_;
|
||||
offset = vector_downward::offset();
|
||||
|
||||
@@ -143,12 +145,14 @@ template<typename SizeT = uoffset_t> class vector_downward {
|
||||
FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
|
||||
// If the length is larger than the unused part of the buffer, we need to
|
||||
// grow.
|
||||
if (len > unused_buffer_size()) { reallocate(len); }
|
||||
if (len > unused_buffer_size()) {
|
||||
reallocate(len);
|
||||
}
|
||||
FLATBUFFERS_ASSERT(size() < max_size_);
|
||||
return len;
|
||||
}
|
||||
|
||||
inline uint8_t *make_space(size_t len) {
|
||||
inline uint8_t* make_space(size_t len) {
|
||||
if (len) {
|
||||
ensure_space(len);
|
||||
cur_ -= len;
|
||||
@@ -158,7 +162,7 @@ template<typename SizeT = uoffset_t> class vector_downward {
|
||||
}
|
||||
|
||||
// Returns nullptr if using the DefaultAllocator.
|
||||
Allocator *get_custom_allocator() { return allocator_; }
|
||||
Allocator* get_custom_allocator() { return allocator_; }
|
||||
|
||||
// The current offset into the buffer.
|
||||
size_t offset() const { return cur_ - buf_; }
|
||||
@@ -167,43 +171,49 @@ template<typename SizeT = uoffset_t> class vector_downward {
|
||||
inline SizeT size() const { return size_; }
|
||||
|
||||
// The size of the buffer part of the vector that is currently unused.
|
||||
SizeT unused_buffer_size() const { return static_cast<SizeT>(cur_ - scratch_); }
|
||||
SizeT unused_buffer_size() const {
|
||||
return static_cast<SizeT>(cur_ - scratch_);
|
||||
}
|
||||
|
||||
// The size of the scratch part of the vector.
|
||||
SizeT scratch_size() const { return static_cast<SizeT>(scratch_ - buf_); }
|
||||
|
||||
size_t capacity() const { return reserved_; }
|
||||
|
||||
uint8_t *data() const {
|
||||
uint8_t* data() const {
|
||||
FLATBUFFERS_ASSERT(cur_);
|
||||
return cur_;
|
||||
}
|
||||
|
||||
uint8_t *scratch_data() const {
|
||||
uint8_t* scratch_data() const {
|
||||
FLATBUFFERS_ASSERT(buf_);
|
||||
return buf_;
|
||||
}
|
||||
|
||||
uint8_t *scratch_end() const {
|
||||
uint8_t* scratch_end() const {
|
||||
FLATBUFFERS_ASSERT(scratch_);
|
||||
return scratch_;
|
||||
}
|
||||
|
||||
uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
|
||||
uint8_t* data_at(size_t offset) const { return buf_ + reserved_ - offset; }
|
||||
|
||||
void push(const uint8_t *bytes, size_t num) {
|
||||
if (num > 0) { memcpy(make_space(num), bytes, num); }
|
||||
void push(const uint8_t* bytes, size_t num) {
|
||||
if (num > 0) {
|
||||
memcpy(make_space(num), bytes, num);
|
||||
}
|
||||
}
|
||||
|
||||
// Specialized version of push() that avoids memcpy call for small data.
|
||||
template<typename T> void push_small(const T &little_endian_t) {
|
||||
template <typename T>
|
||||
void push_small(const T& little_endian_t) {
|
||||
make_space(sizeof(T));
|
||||
*reinterpret_cast<T *>(cur_) = little_endian_t;
|
||||
*reinterpret_cast<T*>(cur_) = little_endian_t;
|
||||
}
|
||||
|
||||
template<typename T> void scratch_push_small(const T &t) {
|
||||
template <typename T>
|
||||
void scratch_push_small(const T& t) {
|
||||
ensure_space(sizeof(T));
|
||||
*reinterpret_cast<T *>(scratch_) = t;
|
||||
*reinterpret_cast<T*>(scratch_) = t;
|
||||
scratch_ += sizeof(T);
|
||||
}
|
||||
|
||||
@@ -227,7 +237,7 @@ template<typename SizeT = uoffset_t> class vector_downward {
|
||||
|
||||
void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
|
||||
|
||||
void swap(vector_downward &other) {
|
||||
void swap(vector_downward& other) {
|
||||
using std::swap;
|
||||
swap(allocator_, other.allocator_);
|
||||
swap(own_allocator_, other.own_allocator_);
|
||||
@@ -241,7 +251,7 @@ template<typename SizeT = uoffset_t> class vector_downward {
|
||||
swap(scratch_, other.scratch_);
|
||||
}
|
||||
|
||||
void swap_allocator(vector_downward &other) {
|
||||
void swap_allocator(vector_downward& other) {
|
||||
using std::swap;
|
||||
swap(allocator_, other.allocator_);
|
||||
swap(own_allocator_, other.own_allocator_);
|
||||
@@ -249,10 +259,10 @@ template<typename SizeT = uoffset_t> class vector_downward {
|
||||
|
||||
private:
|
||||
// You shouldn't really be copying instances of this class.
|
||||
FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &));
|
||||
FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &));
|
||||
FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward&));
|
||||
FLATBUFFERS_DELETE_FUNC(vector_downward& operator=(const vector_downward&));
|
||||
|
||||
Allocator *allocator_;
|
||||
Allocator* allocator_;
|
||||
bool own_allocator_;
|
||||
size_t initial_size_;
|
||||
|
||||
@@ -261,9 +271,9 @@ template<typename SizeT = uoffset_t> class vector_downward {
|
||||
size_t buffer_minalign_;
|
||||
size_t reserved_;
|
||||
SizeT size_;
|
||||
uint8_t *buf_;
|
||||
uint8_t *cur_; // Points at location between empty (below) and used (above).
|
||||
uint8_t *scratch_; // Points to the end of the scratchpad in use.
|
||||
uint8_t* buf_;
|
||||
uint8_t* cur_; // Points at location between empty (below) and used (above).
|
||||
uint8_t* scratch_; // Points to the end of the scratchpad in use.
|
||||
|
||||
void reallocate(size_t len) {
|
||||
auto old_reserved = reserved_;
|
||||
|
||||
+120
-80
@@ -23,7 +23,8 @@
|
||||
namespace flatbuffers {
|
||||
|
||||
// Helper class to verify the integrity of a FlatBuffer
|
||||
class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
template <bool TrackVerifierBufferSize>
|
||||
class VerifierTemplate FLATBUFFERS_FINAL_CLASS {
|
||||
public:
|
||||
struct Options {
|
||||
// The maximum nesting of tables and vectors before we call it invalid.
|
||||
@@ -40,17 +41,18 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
bool assert = false;
|
||||
};
|
||||
|
||||
explicit Verifier(const uint8_t *const buf, const size_t buf_len,
|
||||
const Options &opts)
|
||||
explicit VerifierTemplate(const uint8_t* const buf, const size_t buf_len,
|
||||
const Options& opts)
|
||||
: buf_(buf), size_(buf_len), opts_(opts) {
|
||||
FLATBUFFERS_ASSERT(size_ < opts.max_size);
|
||||
}
|
||||
|
||||
// Deprecated API, please construct with Verifier::Options.
|
||||
Verifier(const uint8_t *const buf, const size_t buf_len,
|
||||
const uoffset_t max_depth = 64, const uoffset_t max_tables = 1000000,
|
||||
const bool check_alignment = true)
|
||||
: Verifier(buf, buf_len, [&] {
|
||||
// Deprecated API, please construct with VerifierTemplate::Options.
|
||||
VerifierTemplate(const uint8_t* const buf, const size_t buf_len,
|
||||
const uoffset_t max_depth = 64,
|
||||
const uoffset_t max_tables = 1000000,
|
||||
const bool check_alignment = true)
|
||||
: VerifierTemplate(buf, buf_len, [&] {
|
||||
Options opts;
|
||||
opts.max_depth = max_depth;
|
||||
opts.max_tables = max_tables;
|
||||
@@ -62,25 +64,25 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
bool Check(const bool ok) const {
|
||||
// clang-format off
|
||||
#ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
|
||||
if (opts_.assert) { FLATBUFFERS_ASSERT(ok); }
|
||||
#endif
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
if (!ok)
|
||||
upper_bound_ = 0;
|
||||
if (opts_.assert) { FLATBUFFERS_ASSERT(ok); }
|
||||
#endif
|
||||
// clang-format on
|
||||
if (TrackVerifierBufferSize) {
|
||||
if (!ok) {
|
||||
upper_bound_ = 0;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Verify any range within the buffer.
|
||||
bool Verify(const size_t elem, const size_t elem_len) const {
|
||||
// clang-format off
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
if (TrackVerifierBufferSize) {
|
||||
auto upper_bound = elem + elem_len;
|
||||
if (upper_bound_ < upper_bound)
|
||||
upper_bound_ = upper_bound;
|
||||
#endif
|
||||
// clang-format on
|
||||
if (upper_bound_ < upper_bound) {
|
||||
upper_bound_ = upper_bound;
|
||||
}
|
||||
}
|
||||
return Check(elem_len < size_ && elem <= size_ - elem_len);
|
||||
}
|
||||
|
||||
@@ -89,59 +91,61 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
}
|
||||
|
||||
// Verify a range indicated by sizeof(T).
|
||||
template<typename T> bool Verify(const size_t elem) const {
|
||||
template <typename T>
|
||||
bool Verify(const size_t elem) const {
|
||||
return VerifyAlignment(elem, sizeof(T)) && Verify(elem, sizeof(T));
|
||||
}
|
||||
|
||||
bool VerifyFromPointer(const uint8_t *const p, const size_t len) {
|
||||
bool VerifyFromPointer(const uint8_t* const p, const size_t len) {
|
||||
return Verify(static_cast<size_t>(p - buf_), len);
|
||||
}
|
||||
|
||||
// Verify relative to a known-good base pointer.
|
||||
bool VerifyFieldStruct(const uint8_t *const base, const voffset_t elem_off,
|
||||
bool VerifyFieldStruct(const uint8_t* const base, const voffset_t elem_off,
|
||||
const size_t elem_len, const size_t align) const {
|
||||
const auto f = static_cast<size_t>(base - buf_) + elem_off;
|
||||
return VerifyAlignment(f, align) && Verify(f, elem_len);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool VerifyField(const uint8_t *const base, const voffset_t elem_off,
|
||||
template <typename T>
|
||||
bool VerifyField(const uint8_t* const base, const voffset_t elem_off,
|
||||
const size_t align) const {
|
||||
const auto f = static_cast<size_t>(base - buf_) + elem_off;
|
||||
return VerifyAlignment(f, align) && Verify(f, sizeof(T));
|
||||
}
|
||||
|
||||
// Verify a pointer (may be NULL) of a table type.
|
||||
template<typename T> bool VerifyTable(const T *const table) {
|
||||
template <typename T>
|
||||
bool VerifyTable(const T* const table) {
|
||||
return !table || table->Verify(*this);
|
||||
}
|
||||
|
||||
// Verify a pointer (may be NULL) of any vector type.
|
||||
template<int &..., typename T, typename LenT>
|
||||
bool VerifyVector(const Vector<T, LenT> *const vec) const {
|
||||
template <int&..., typename T, typename LenT>
|
||||
bool VerifyVector(const Vector<T, LenT>* const vec) const {
|
||||
return !vec || VerifyVectorOrString<LenT>(
|
||||
reinterpret_cast<const uint8_t *>(vec), sizeof(T));
|
||||
reinterpret_cast<const uint8_t*>(vec), sizeof(T));
|
||||
}
|
||||
|
||||
// Verify a pointer (may be NULL) of a vector to struct.
|
||||
template<int &..., typename T, typename LenT>
|
||||
bool VerifyVector(const Vector<const T *, LenT> *const vec) const {
|
||||
return VerifyVector(reinterpret_cast<const Vector<T, LenT> *>(vec));
|
||||
template <int&..., typename T, typename LenT>
|
||||
bool VerifyVector(const Vector<const T*, LenT>* const vec) const {
|
||||
return VerifyVector(reinterpret_cast<const Vector<T, LenT>*>(vec));
|
||||
}
|
||||
|
||||
// Verify a pointer (may be NULL) to string.
|
||||
bool VerifyString(const String *const str) const {
|
||||
bool VerifyString(const String* const str) const {
|
||||
size_t end;
|
||||
return !str || (VerifyVectorOrString<uoffset_t>(
|
||||
reinterpret_cast<const uint8_t *>(str), 1, &end) &&
|
||||
reinterpret_cast<const uint8_t*>(str), 1, &end) &&
|
||||
Verify(end, 1) && // Must have terminator
|
||||
Check(buf_[end] == '\0')); // Terminating byte must be 0.
|
||||
}
|
||||
|
||||
// Common code between vectors and strings.
|
||||
template<typename LenT = uoffset_t>
|
||||
bool VerifyVectorOrString(const uint8_t *const vec, const size_t elem_size,
|
||||
size_t *const end = nullptr) const {
|
||||
template <typename LenT = uoffset_t>
|
||||
bool VerifyVectorOrString(const uint8_t* const vec, const size_t elem_size,
|
||||
size_t* const end = nullptr) const {
|
||||
const auto vec_offset = static_cast<size_t>(vec - buf_);
|
||||
// Check we can read the size field.
|
||||
if (!Verify<LenT>(vec_offset)) return false;
|
||||
@@ -157,7 +161,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
}
|
||||
|
||||
// Special case for string contents, after the above has been called.
|
||||
bool VerifyVectorOfStrings(const Vector<Offset<String>> *const vec) const {
|
||||
bool VerifyVectorOfStrings(const Vector<Offset<String>>* const vec) const {
|
||||
if (vec) {
|
||||
for (uoffset_t i = 0; i < vec->size(); i++) {
|
||||
if (!VerifyString(vec->Get(i))) return false;
|
||||
@@ -167,8 +171,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
}
|
||||
|
||||
// Special case for table contents, after the above has been called.
|
||||
template<typename T>
|
||||
bool VerifyVectorOfTables(const Vector<Offset<T>> *const vec) {
|
||||
template <typename T>
|
||||
bool VerifyVectorOfTables(const Vector<Offset<T>>* const vec) {
|
||||
if (vec) {
|
||||
for (uoffset_t i = 0; i < vec->size(); i++) {
|
||||
if (!vec->Get(i)->Verify(*this)) return false;
|
||||
@@ -177,8 +181,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
return true;
|
||||
}
|
||||
|
||||
__suppress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
|
||||
const uint8_t *const table) {
|
||||
FLATBUFFERS_SUPPRESS_UBSAN("unsigned-integer-overflow")
|
||||
bool VerifyTableStart(const uint8_t* const table) {
|
||||
// Check the vtable offset.
|
||||
const auto tableo = static_cast<size_t>(table - buf_);
|
||||
if (!Verify<soffset_t>(tableo)) return false;
|
||||
@@ -195,8 +199,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
return Check((vsize & 1) == 0) && Verify(vtableo, vsize);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool VerifyBufferFromStart(const char *const identifier, const size_t start) {
|
||||
template <typename T>
|
||||
bool VerifyBufferFromStart(const char* const identifier, const size_t start) {
|
||||
// Buffers have to be of some size to be valid. The reason it is a runtime
|
||||
// check instead of static_assert, is that nested flatbuffers go through
|
||||
// this call and their size is determined at runtime.
|
||||
@@ -210,19 +214,19 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
|
||||
// Call T::Verify, which must be in the generated code for this type.
|
||||
const auto o = VerifyOffset<uoffset_t>(start);
|
||||
return Check(o != 0) &&
|
||||
reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
|
||||
// clang-format off
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
&& GetComputedSize()
|
||||
#endif
|
||||
;
|
||||
// clang-format on
|
||||
if (!Check(o != 0)) return false;
|
||||
if (!(reinterpret_cast<const T*>(buf_ + start + o)->Verify(*this))) {
|
||||
return false;
|
||||
}
|
||||
if (TrackVerifierBufferSize) {
|
||||
if (GetComputedSize() == 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, int &..., typename SizeT>
|
||||
bool VerifyNestedFlatBuffer(const Vector<uint8_t, SizeT> *const buf,
|
||||
const char *const identifier) {
|
||||
template <typename T, int&..., typename SizeT>
|
||||
bool VerifyNestedFlatBuffer(const Vector<uint8_t, SizeT>* const buf,
|
||||
const char* const identifier) {
|
||||
// Caller opted out of this.
|
||||
if (!opts_.check_nested_flatbuffers) return true;
|
||||
|
||||
@@ -232,25 +236,32 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
// If there is a nested buffer, it must be greater than the min size.
|
||||
if (!Check(buf->size() >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false;
|
||||
|
||||
Verifier nested_verifier(buf->data(), buf->size(), opts_);
|
||||
VerifierTemplate<TrackVerifierBufferSize> nested_verifier(
|
||||
buf->data(), buf->size(), opts_);
|
||||
return nested_verifier.VerifyBuffer<T>(identifier);
|
||||
}
|
||||
|
||||
// Verify this whole buffer, starting with root type T.
|
||||
template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
|
||||
template <typename T>
|
||||
bool VerifyBuffer() {
|
||||
return VerifyBuffer<T>(nullptr);
|
||||
}
|
||||
|
||||
template<typename T> bool VerifyBuffer(const char *const identifier) {
|
||||
template <typename T>
|
||||
bool VerifyBuffer(const char* const identifier) {
|
||||
return VerifyBufferFromStart<T>(identifier, 0);
|
||||
}
|
||||
|
||||
template<typename T, typename SizeT = uoffset_t>
|
||||
bool VerifySizePrefixedBuffer(const char *const identifier) {
|
||||
template <typename T, typename SizeT = uoffset_t>
|
||||
bool VerifySizePrefixedBuffer(const char* const identifier) {
|
||||
return Verify<SizeT>(0U) &&
|
||||
Check(ReadScalar<SizeT>(buf_) == size_ - sizeof(SizeT)) &&
|
||||
// Ensure the prefixed size is within the bounds of the provided
|
||||
// length.
|
||||
Check(ReadScalar<SizeT>(buf_) + sizeof(SizeT) <= size_) &&
|
||||
VerifyBufferFromStart<T>(identifier, sizeof(SizeT));
|
||||
}
|
||||
|
||||
template<typename OffsetT = uoffset_t, typename SOffsetT = soffset_t>
|
||||
template <typename OffsetT = uoffset_t, typename SOffsetT = soffset_t>
|
||||
size_t VerifyOffset(const size_t start) const {
|
||||
if (!Verify<OffsetT>(start)) return 0;
|
||||
const auto o = ReadScalar<OffsetT>(buf_ + start);
|
||||
@@ -264,8 +275,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
return o;
|
||||
}
|
||||
|
||||
template<typename OffsetT = uoffset_t>
|
||||
size_t VerifyOffset(const uint8_t *const base, const voffset_t start) const {
|
||||
template <typename OffsetT = uoffset_t>
|
||||
size_t VerifyOffset(const uint8_t* const base, const voffset_t start) const {
|
||||
return VerifyOffset<OffsetT>(static_cast<size_t>(base - buf_) + start);
|
||||
}
|
||||
|
||||
@@ -284,31 +295,37 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the message size in bytes
|
||||
// Returns the message size in bytes.
|
||||
//
|
||||
// This should only be called after first calling VerifyBuffer or
|
||||
// VerifySizePrefixedBuffer.
|
||||
//
|
||||
// This method should only be called for VerifierTemplate instances
|
||||
// where the TrackVerifierBufferSize template parameter is true,
|
||||
// i.e. for SizeVerifier. For instances where TrackVerifierBufferSize
|
||||
// is false, this fails at runtime or returns zero.
|
||||
size_t GetComputedSize() const {
|
||||
// clang-format off
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
if (TrackVerifierBufferSize) {
|
||||
uintptr_t size = upper_bound_;
|
||||
// Align the size to uoffset_t
|
||||
size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
|
||||
return (size > size_) ? 0 : size;
|
||||
#else
|
||||
// Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
|
||||
(void)upper_bound_;
|
||||
FLATBUFFERS_ASSERT(false);
|
||||
return 0;
|
||||
#endif
|
||||
// clang-format on
|
||||
return (size > size_) ? 0 : size;
|
||||
}
|
||||
// Must use SizeVerifier, or (deprecated) turn on
|
||||
// FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE, for this to work.
|
||||
(void)upper_bound_;
|
||||
FLATBUFFERS_ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> *GetFlexReuseTracker() { return flex_reuse_tracker_; }
|
||||
std::vector<uint8_t>* GetFlexReuseTracker() { return flex_reuse_tracker_; }
|
||||
|
||||
void SetFlexReuseTracker(std::vector<uint8_t> *const rt) {
|
||||
void SetFlexReuseTracker(std::vector<uint8_t>* const rt) {
|
||||
flex_reuse_tracker_ = rt;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t *buf_;
|
||||
const uint8_t* buf_;
|
||||
const size_t size_;
|
||||
const Options opts_;
|
||||
|
||||
@@ -316,14 +333,37 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
|
||||
uoffset_t depth_ = 0;
|
||||
uoffset_t num_tables_ = 0;
|
||||
std::vector<uint8_t> *flex_reuse_tracker_ = nullptr;
|
||||
std::vector<uint8_t>* flex_reuse_tracker_ = nullptr;
|
||||
};
|
||||
|
||||
// Specialization for 64-bit offsets.
|
||||
template<>
|
||||
inline size_t Verifier::VerifyOffset<uoffset64_t>(const size_t start) const {
|
||||
template <>
|
||||
template <>
|
||||
inline size_t VerifierTemplate<false>::VerifyOffset<uoffset64_t>(
|
||||
const size_t start) const {
|
||||
return VerifyOffset<uoffset64_t, soffset64_t>(start);
|
||||
}
|
||||
template <>
|
||||
template <>
|
||||
inline size_t VerifierTemplate<true>::VerifyOffset<uoffset64_t>(
|
||||
const size_t start) const {
|
||||
return VerifyOffset<uoffset64_t, soffset64_t>(start);
|
||||
}
|
||||
|
||||
// Instance of VerifierTemplate that supports GetComputedSize().
|
||||
using SizeVerifier = VerifierTemplate</*TrackVerifierBufferSize = */ true>;
|
||||
|
||||
// The FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE build configuration macro is
|
||||
// deprecated, and should not be defined, since it is easy to misuse in ways
|
||||
// that result in ODR violations. Rather than using Verifier and defining
|
||||
// FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE, please use SizeVerifier instead.
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE // Deprecated, see above.
|
||||
using Verifier = SizeVerifier;
|
||||
#else
|
||||
// Instance of VerifierTemplate that is slightly faster, but does not
|
||||
// support GetComputedSize().
|
||||
using Verifier = VerifierTemplate</*TrackVerifierBufferSize = */ false>;
|
||||
#endif
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
if(WITH_FLATBUFFERS)
|
||||
set(HAVE_FLATBUFFERS 1)
|
||||
set(flatbuffers_VERSION "23.5.9")
|
||||
set(flatbuffers_VERSION "25.9.23")
|
||||
ocv_install_3rdparty_licenses(flatbuffers "${OpenCV_SOURCE_DIR}/3rdparty/flatbuffers/LICENSE.txt")
|
||||
ocv_add_external_target(flatbuffers "${OpenCV_SOURCE_DIR}/3rdparty/flatbuffers/include" "" "HAVE_FLATBUFFERS=1")
|
||||
set(CUSTOM_STATUS_flatbuffers " Flatbuffers:" "builtin/3rdparty (${flatbuffers_VERSION})")
|
||||
|
||||
@@ -20,8 +20,10 @@ if(NOT OpenBLAS_FOUND)
|
||||
endif()
|
||||
|
||||
if(NOT OpenBLAS_FOUND)
|
||||
find_library(OpenBLAS_LIBRARIES NAMES openblas)
|
||||
find_path(OpenBLAS_INCLUDE_DIRS NAMES cblas.h)
|
||||
find_library(OpenBLAS_LIBRARIES NAMES openblasp openblas)
|
||||
find_path(OpenBLAS_INCLUDE_DIRS
|
||||
NAMES cblas.h
|
||||
PATH_SUFFIXES openblas)
|
||||
find_path(OpenBLAS_LAPACKE_DIR NAMES lapacke.h PATHS "${OpenBLAS_INCLUDE_DIRS}")
|
||||
if(OpenBLAS_LIBRARIES AND OpenBLAS_INCLUDE_DIRS)
|
||||
message(STATUS "Found OpenBLAS in the system")
|
||||
|
||||
@@ -6,6 +6,11 @@ Using Creative Senz3D and other Intel RealSense SDK compatible depth sensors {#t
|
||||
@prev_tutorial{tutorial_orbbec_uvc}
|
||||
@next_tutorial{tutorial_wayland_ubuntu}
|
||||
|
||||
| | |
|
||||
| -: | :- |
|
||||
| Original author | Alessandro de Oliveira Faria |
|
||||
| Compatibility | OpenCV >= 4.5.5 |
|
||||
|
||||

|
||||
|
||||
**Note**: This tutorial is partially obsolete since PerC SDK has been replaced with RealSense SDK
|
||||
|
||||
@@ -2544,7 +2544,7 @@ void undistortPoints(InputArray src, OutputArray dst,
|
||||
CV_EXPORTS_W
|
||||
void undistortImagePoints(InputArray src, OutputArray dst, InputArray cameraMatrix,
|
||||
InputArray distCoeffs,
|
||||
TermCriteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 0.01));
|
||||
TermCriteria = TermCriteria(TermCriteria::MAX_ITER, 5, 0.01));
|
||||
|
||||
namespace fisheye {
|
||||
|
||||
|
||||
@@ -437,8 +437,12 @@ static void undistortPointsInternal( const Mat& _src, Mat& _dst, const Mat& _cam
|
||||
y0 = y = invProj * vecUntilt(1);
|
||||
|
||||
double error = std::numeric_limits<double>::max();
|
||||
double prevError = std::numeric_limits<double>::max();
|
||||
// compensate distortion iteratively using fixed-point iteration
|
||||
|
||||
// parameter for damped fixed-point iteration
|
||||
double alpha = 1.;
|
||||
|
||||
for( int j = 0; ; j++ )
|
||||
{
|
||||
if ((criteria.type & TermCriteria::COUNT) && j >= criteria.maxCount)
|
||||
@@ -462,10 +466,11 @@ static void undistortPointsInternal( const Mat& _src, Mat& _dst, const Mat& _cam
|
||||
// [x'', y'']^T = [x' / icdist + deltaX, y' / icdist + deltaY]^T =>
|
||||
// [x', y']^T = [(x'' - deltaX) * icdist, (y'' - deltaY) * icdist]^T =>
|
||||
// x' = f1(x') := (x'' - deltaX) * icdist, y' = f2(y') := (y'' - deltaY) * icdist
|
||||
// Fixed-point iteration:
|
||||
// new_x' = f1(x') = (x'' - deltaX) * icdist, new_y' = f2(y') = (y'' - deltaY) * icdist
|
||||
x = (x0 - deltaX)*icdist;
|
||||
y = (y0 - deltaY)*icdist;
|
||||
// Damped fixed-point iteration:
|
||||
// f1(x') = (x'' - deltaX) * icdist, f2(y') = (y'' - deltaY) * icdist
|
||||
// new_x' = (1 - alpha) * x' + alpha * f1(x'), new_y' = (1 - alpha) * y' + alpha * f2(y')
|
||||
double new_x = (1. - alpha)*x + alpha*(x0 - deltaX)*icdist;
|
||||
double new_y = (1. - alpha)*y + alpha*(y0 - deltaY)*icdist;
|
||||
|
||||
if(criteria.type & TermCriteria::EPS)
|
||||
{
|
||||
@@ -474,20 +479,20 @@ static void undistortPointsInternal( const Mat& _src, Mat& _dst, const Mat& _cam
|
||||
Vec3d vecTilt;
|
||||
|
||||
// r^2 = x'^2 + y'^2
|
||||
r2 = x*x + y*y;
|
||||
r2 = new_x*new_x + new_y*new_y;
|
||||
r4 = r2*r2;
|
||||
r6 = r4*r2;
|
||||
a1 = 2*x*y;
|
||||
a2 = r2 + 2*x*x;
|
||||
a3 = r2 + 2*y*y;
|
||||
a1 = 2*new_x*new_y;
|
||||
a2 = r2 + 2*new_x*new_x;
|
||||
a3 = r2 + 2*new_y*new_y;
|
||||
// cdist := 1 + k1 * r^2 + k2 * r^4 + k3 * r^6
|
||||
cdist = 1 + k[0]*r2 + k[1]*r4 + k[4]*r6;
|
||||
// icdist2 := 1 / (1 + k4 * r^2 + k5 * r^4 + k6 * r^6)
|
||||
icdist2 = 1./(1 + k[5]*r2 + k[6]*r4 + k[7]*r6);
|
||||
// x'' = x' * cdist * icdist2 + 2 * p1 * x' * y' + p2 * (r^2 + 2 * x'^2) + s1 * r^2 + s2 * r^4
|
||||
// y'' = y' * cdist * icdist2 + p1 * (r^2 + 2 * y'^2) + 2 * p2 * x' * y' + s3 * r^2 + s4 * r^4
|
||||
xd0 = x*cdist*icdist2 + k[2]*a1 + k[3]*a2 + k[8]*r2+k[9]*r4;
|
||||
yd0 = y*cdist*icdist2 + k[2]*a3 + k[3]*a1 + k[10]*r2+k[11]*r4;
|
||||
xd0 = new_x*cdist*icdist2 + k[2]*a1 + k[3]*a2 + k[8]*r2+k[9]*r4;
|
||||
yd0 = new_y*cdist*icdist2 + k[2]*a3 + k[3]*a1 + k[10]*r2+k[11]*r4;
|
||||
|
||||
// s * [x''', y''', 1]^T = matTilt * [x'', y'', 1]^T =>
|
||||
// (vecTilt := matTilt * [x'', y'', 1]^T)
|
||||
@@ -505,6 +510,13 @@ static void undistortPointsInternal( const Mat& _src, Mat& _dst, const Mat& _cam
|
||||
|
||||
error = sqrt( pow(x_proj - u, 2) + pow(y_proj - v, 2) );
|
||||
}
|
||||
if (error > prevError) {
|
||||
alpha *= .5;
|
||||
} else {
|
||||
x = new_x;
|
||||
y = new_y;
|
||||
}
|
||||
prevError = error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ protected:
|
||||
void generateCameraMatrix(Mat& cameraMatrix);
|
||||
void generateDistCoeffs(Mat& distCoeffs, int count);
|
||||
cv::Mat generateRotationVector();
|
||||
std::vector<cv::Point2d> distortPoints(const cv::Mat &cameraMatrix, const cv::Mat &dist, const std::vector<cv::Point2d> &points);
|
||||
|
||||
double thresh = 1.0e-2;
|
||||
};
|
||||
@@ -60,6 +61,34 @@ cv::Mat UndistortPointsTest::generateRotationVector()
|
||||
return rvec;
|
||||
}
|
||||
|
||||
std::vector<cv::Point2d> UndistortPointsTest::distortPoints(const cv::Mat &cameraMatrix, const cv::Mat &dist, const std::vector<cv::Point2d> &points)
|
||||
{
|
||||
CV_Assert(cameraMatrix.rows == 3 && cameraMatrix.cols == 3);
|
||||
CV_Assert(cameraMatrix.type() == CV_64F);
|
||||
CV_Assert(dist.rows * dist.cols == 12);
|
||||
CV_Assert(dist.type() == CV_64F);
|
||||
double *k = reinterpret_cast<double *>(dist.data);
|
||||
double fx = cameraMatrix.at<double>(0, 0);
|
||||
double fy = cameraMatrix.at<double>(1, 1);
|
||||
double cx = cameraMatrix.at<double>(0, 2);
|
||||
double cy = cameraMatrix.at<double>(1, 2);
|
||||
std::vector<cv::Point2d> distortedPoints;
|
||||
distortedPoints.reserve(points.size());
|
||||
|
||||
for (const cv::Point2d p : points) {
|
||||
double x = (p.x - cx) / fx;
|
||||
double y = (p.y - cy) / fy;
|
||||
double r2 = x*x + y*y;
|
||||
double cdist = (1 + ((k[4]*r2 + k[1])*r2 + k[0])*r2)/(1 + ((k[7]*r2 + k[6])*r2 + k[5])*r2);
|
||||
CV_Assert(cdist >= 0);
|
||||
double deltaX = 2*k[2]*x*y + k[3]*(r2 + 2*x*x)+ k[8]*r2+k[9]*r2*r2;
|
||||
double deltaY = k[2]*(r2 + 2*y*y) + 2*k[3]*x*y+ k[10]*r2+k[11]*r2*r2;
|
||||
distortedPoints.push_back(cv::Point2d((x * cdist + deltaX) * fx + cx, (y * cdist + deltaY) * fy + cy));
|
||||
}
|
||||
|
||||
return distortedPoints;
|
||||
}
|
||||
|
||||
TEST_F(UndistortPointsTest, accuracy)
|
||||
{
|
||||
Mat intrinsics, distCoeffs;
|
||||
@@ -196,4 +225,33 @@ TEST_F(UndistortPointsTest, regression_14583)
|
||||
<< "undistort point: " << undistort_pt;
|
||||
}
|
||||
|
||||
TEST_F(UndistortPointsTest, regression_27916)
|
||||
{
|
||||
cv::Mat K = (cv::Mat_<double>(3, 3) <<
|
||||
1570.8956145992222, 0., 744.87337646727406, 0.,
|
||||
1570.3494207432338, 575.55087456337526, 0., 0., 1.);
|
||||
cv::Mat dist = (cv::Mat_<double>(1, 12) <<
|
||||
-2.8247717583453804, -0.80078070764368037,
|
||||
-0.014595359484103326, 0.0018820998949700702, 1.9827795585249783,
|
||||
-2.7306773773930897, -1.217725820479524, 2.4052243546080136,
|
||||
-0.0020670359760441713, 3.4660880793174063e-05,
|
||||
0.014100351510458799, -3.0935329736207612e-05);
|
||||
|
||||
const cv::TermCriteria termCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS, 100, thresh / 2);
|
||||
std::vector<cv::Point2d> distortedPoints, distortedPoints2;
|
||||
std::vector<cv::Point2d> undistortedPoints;
|
||||
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
for (int j = 0; j < 50; j++)
|
||||
{
|
||||
distortedPoints.push_back(cv::Point2d(i, j));
|
||||
}
|
||||
}
|
||||
|
||||
cv::undistortPoints(distortedPoints, undistortedPoints, K, dist, cv::noArray(), K, termCriteria);
|
||||
distortedPoints2 = distortPoints(K, dist, undistortedPoints);
|
||||
EXPECT_MAT_NEAR(distortedPoints2, distortedPoints, thresh);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -201,7 +201,7 @@ cvRound( double value )
|
||||
{
|
||||
#if defined CV_INLINE_ROUND_DBL
|
||||
CV_INLINE_ROUND_DBL(value);
|
||||
#elif defined _MSC_VER && defined _M_ARM64
|
||||
#elif defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC))
|
||||
float64x1_t v = vdup_n_f64(value);
|
||||
int64x1_t r = vcvtn_s64_f64(v);
|
||||
return static_cast<int>(vget_lane_s64(r, 0));
|
||||
@@ -327,7 +327,7 @@ CV_INLINE int cvRound(float value)
|
||||
{
|
||||
#if defined CV_INLINE_ROUND_FLT
|
||||
CV_INLINE_ROUND_FLT(value);
|
||||
#elif defined _MSC_VER && defined _M_ARM64
|
||||
#elif defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC))
|
||||
float32x2_t v = vdup_n_f32(value);
|
||||
int32x2_t r = vcvtn_s32_f32(v);
|
||||
return vget_lane_s32(r, 0);
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace ogl
|
||||
namespace cuda
|
||||
{
|
||||
class CV_EXPORTS GpuMat;
|
||||
class CV_EXPORTS GpuMatND;
|
||||
class CV_EXPORTS HostMem;
|
||||
class CV_EXPORTS Stream;
|
||||
class CV_EXPORTS Event;
|
||||
|
||||
@@ -287,7 +287,8 @@ public:
|
||||
STD_VECTOR_UMAT =11 << KIND_SHIFT,
|
||||
STD_BOOL_VECTOR =12 << KIND_SHIFT,
|
||||
STD_VECTOR_CUDA_GPU_MAT = 13 << KIND_SHIFT,
|
||||
STD_ARRAY_MAT =15 << KIND_SHIFT
|
||||
STD_ARRAY_MAT =15 << KIND_SHIFT,
|
||||
CUDA_GPU_MATND =16 << KIND_SHIFT
|
||||
};
|
||||
|
||||
_InputArray();
|
||||
@@ -306,6 +307,7 @@ public:
|
||||
_InputArray(const double& val);
|
||||
_InputArray(const cuda::GpuMat& d_mat);
|
||||
_InputArray(const std::vector<cuda::GpuMat>& d_mat_array);
|
||||
_InputArray(const cuda::GpuMatND& d_mat);
|
||||
_InputArray(const ogl::Buffer& buf);
|
||||
_InputArray(const cuda::HostMem& cuda_mem);
|
||||
template<typename _Tp> _InputArray(const cudev::GpuMat_<_Tp>& m);
|
||||
@@ -325,6 +327,7 @@ public:
|
||||
void getUMatVector(std::vector<UMat>& umv) const;
|
||||
void getGpuMatVector(std::vector<cuda::GpuMat>& gpumv) const;
|
||||
cuda::GpuMat getGpuMat() const;
|
||||
cuda::GpuMatND getGpuMatND() const;
|
||||
ogl::Buffer getOGlBuffer() const;
|
||||
|
||||
int getFlags() const;
|
||||
@@ -360,6 +363,7 @@ public:
|
||||
bool isVector() const;
|
||||
bool isGpuMat() const;
|
||||
bool isGpuMatVector() const;
|
||||
bool isGpuMatND() const;
|
||||
~_InputArray();
|
||||
|
||||
protected:
|
||||
@@ -428,6 +432,7 @@ public:
|
||||
_OutputArray(std::vector<Mat>& vec);
|
||||
_OutputArray(cuda::GpuMat& d_mat);
|
||||
_OutputArray(std::vector<cuda::GpuMat>& d_mat);
|
||||
_OutputArray(cuda::GpuMatND& d_mat);
|
||||
_OutputArray(ogl::Buffer& buf);
|
||||
_OutputArray(cuda::HostMem& cuda_mem);
|
||||
template<typename _Tp> _OutputArray(cudev::GpuMat_<_Tp>& m);
|
||||
@@ -446,6 +451,7 @@ public:
|
||||
_OutputArray(const std::vector<Mat>& vec);
|
||||
_OutputArray(const cuda::GpuMat& d_mat);
|
||||
_OutputArray(const std::vector<cuda::GpuMat>& d_mat);
|
||||
_OutputArray(const cuda::GpuMatND& d_mat);
|
||||
_OutputArray(const ogl::Buffer& buf);
|
||||
_OutputArray(const cuda::HostMem& cuda_mem);
|
||||
template<typename _Tp> _OutputArray(const cudev::GpuMat_<_Tp>& m);
|
||||
@@ -476,6 +482,7 @@ public:
|
||||
std::vector<Mat>& getMatVecRef() const;
|
||||
std::vector<UMat>& getUMatVecRef() const;
|
||||
template<typename _Tp> std::vector<std::vector<_Tp> >& getVecVecRef() const;
|
||||
cuda::GpuMatND& getGpuMatNDRef() const;
|
||||
ogl::Buffer& getOGlBufferRef() const;
|
||||
cuda::HostMem& getHostMemRef() const;
|
||||
|
||||
@@ -516,6 +523,7 @@ public:
|
||||
_InputOutputArray(Mat& m);
|
||||
_InputOutputArray(std::vector<Mat>& vec);
|
||||
_InputOutputArray(cuda::GpuMat& d_mat);
|
||||
_InputOutputArray(cuda::GpuMatND& d_mat);
|
||||
_InputOutputArray(ogl::Buffer& buf);
|
||||
_InputOutputArray(cuda::HostMem& cuda_mem);
|
||||
template<typename _Tp> _InputOutputArray(cudev::GpuMat_<_Tp>& m);
|
||||
@@ -533,6 +541,7 @@ public:
|
||||
_InputOutputArray(const std::vector<Mat>& vec);
|
||||
_InputOutputArray(const cuda::GpuMat& d_mat);
|
||||
_InputOutputArray(const std::vector<cuda::GpuMat>& d_mat);
|
||||
_InputOutputArray(const cuda::GpuMatND& d_mat);
|
||||
_InputOutputArray(const ogl::Buffer& buf);
|
||||
_InputOutputArray(const cuda::HostMem& cuda_mem);
|
||||
template<typename _Tp> _InputOutputArray(const cudev::GpuMat_<_Tp>& m);
|
||||
|
||||
@@ -214,7 +214,10 @@ inline _InputArray::_InputArray(const cuda::GpuMat& d_mat)
|
||||
{ init(+CUDA_GPU_MAT + ACCESS_READ, &d_mat); }
|
||||
|
||||
inline _InputArray::_InputArray(const std::vector<cuda::GpuMat>& d_mat)
|
||||
{ init(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_READ, &d_mat);}
|
||||
{ init(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_READ, &d_mat);}
|
||||
|
||||
inline _InputArray::_InputArray(const cuda::GpuMatND& d_mat)
|
||||
{ init(+CUDA_GPU_MATND + ACCESS_READ, &d_mat); }
|
||||
|
||||
inline _InputArray::_InputArray(const ogl::Buffer& buf)
|
||||
{ init(+OPENGL_BUFFER + ACCESS_READ, &buf); }
|
||||
@@ -261,6 +264,7 @@ inline bool _InputArray::isVector() const { return kind() == _InputArray::STD_VE
|
||||
(kind() == _InputArray::MATX && (sz.width <= 1 || sz.height <= 1)); }
|
||||
inline bool _InputArray::isGpuMat() const { return kind() == _InputArray::CUDA_GPU_MAT; }
|
||||
inline bool _InputArray::isGpuMatVector() const { return kind() == _InputArray::STD_VECTOR_CUDA_GPU_MAT; }
|
||||
inline bool _InputArray::isGpuMatND() const { return kind() == _InputArray::CUDA_GPU_MATND; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -339,7 +343,10 @@ inline _OutputArray::_OutputArray(cuda::GpuMat& d_mat)
|
||||
{ init(+CUDA_GPU_MAT + ACCESS_WRITE, &d_mat); }
|
||||
|
||||
inline _OutputArray::_OutputArray(std::vector<cuda::GpuMat>& d_mat)
|
||||
{ init(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_WRITE, &d_mat);}
|
||||
{ init(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_WRITE, &d_mat);}
|
||||
|
||||
inline _OutputArray::_OutputArray(cuda::GpuMatND& d_mat)
|
||||
{ init(+CUDA_GPU_MATND + ACCESS_WRITE, &d_mat); }
|
||||
|
||||
inline _OutputArray::_OutputArray(ogl::Buffer& buf)
|
||||
{ init(+OPENGL_BUFFER + ACCESS_WRITE, &buf); }
|
||||
@@ -362,6 +369,8 @@ inline _OutputArray::_OutputArray(const std::vector<UMat>& vec)
|
||||
inline _OutputArray::_OutputArray(const cuda::GpuMat& d_mat)
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MAT + ACCESS_WRITE, &d_mat); }
|
||||
|
||||
inline _OutputArray::_OutputArray(const cuda::GpuMatND& d_mat)
|
||||
{ init(+FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MATND + ACCESS_WRITE, &d_mat); }
|
||||
|
||||
inline _OutputArray::_OutputArray(const ogl::Buffer& buf)
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER + ACCESS_WRITE, &buf); }
|
||||
@@ -486,6 +495,9 @@ _InputOutputArray::_InputOutputArray(const _Tp* vec, int n)
|
||||
inline _InputOutputArray::_InputOutputArray(cuda::GpuMat& d_mat)
|
||||
{ init(+CUDA_GPU_MAT + ACCESS_RW, &d_mat); }
|
||||
|
||||
inline _InputOutputArray::_InputOutputArray(cuda::GpuMatND& d_mat)
|
||||
{ init(+CUDA_GPU_MATND + ACCESS_RW, &d_mat); }
|
||||
|
||||
inline _InputOutputArray::_InputOutputArray(ogl::Buffer& buf)
|
||||
{ init(+OPENGL_BUFFER + ACCESS_RW, &buf); }
|
||||
|
||||
@@ -513,6 +525,9 @@ inline _InputOutputArray::_InputOutputArray(const std::vector<cuda::GpuMat>& d_m
|
||||
template<> inline _InputOutputArray::_InputOutputArray(std::vector<cuda::GpuMat>& d_mat)
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_CUDA_GPU_MAT + ACCESS_RW, &d_mat);}
|
||||
|
||||
inline _InputOutputArray::_InputOutputArray(const cuda::GpuMatND& d_mat)
|
||||
{ init(+FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MATND + ACCESS_RW, &d_mat); }
|
||||
|
||||
inline _InputOutputArray::_InputOutputArray(const ogl::Buffer& buf)
|
||||
{ init(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER + ACCESS_RW, &buf); }
|
||||
|
||||
|
||||
@@ -113,6 +113,12 @@ Mat _InputArray::getMat_(int i) const
|
||||
CV_Error(cv::Error::StsNotImplemented, "You should explicitly call download method for cuda::GpuMat object");
|
||||
}
|
||||
|
||||
if( k == CUDA_GPU_MATND )
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
CV_Error(cv::Error::StsNotImplemented, "You should explicitly call download method for cuda::GpuMatND object");
|
||||
}
|
||||
|
||||
if( k == CUDA_HOST_MEM )
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
@@ -360,6 +366,22 @@ void _InputArray::getGpuMatVector(std::vector<cuda::GpuMat>& gpumv) const
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
cuda::GpuMatND _InputArray::getGpuMatND() const
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
_InputArray::KindFlag k = kind();
|
||||
|
||||
if (k == CUDA_GPU_MATND)
|
||||
{
|
||||
const cuda::GpuMatND* d_mat = (const cuda::GpuMatND*)obj;
|
||||
return *d_mat;
|
||||
}
|
||||
|
||||
CV_Error(cv::Error::StsNotImplemented, "getGpuMatND is available only for cuda::GpuMatND");
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
ogl::Buffer _InputArray::getOGlBuffer() const
|
||||
{
|
||||
_InputArray::KindFlag k = kind();
|
||||
@@ -382,11 +404,29 @@ _InputArray::KindFlag _InputArray::kind() const
|
||||
|
||||
int _InputArray::rows(int i) const
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
_InputArray::KindFlag k = kind();
|
||||
if (k == CUDA_GPU_MATND)
|
||||
{
|
||||
const cuda::GpuMatND& _gpuMatND = *(const cuda::GpuMatND*)obj;
|
||||
return (_gpuMatND.dims < 1) ? 0 : _gpuMatND.size[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
return size(i).height;
|
||||
}
|
||||
|
||||
int _InputArray::cols(int i) const
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
_InputArray::KindFlag k = kind();
|
||||
if (k == CUDA_GPU_MATND)
|
||||
{
|
||||
const cuda::GpuMatND& _gpuMatND = *(const cuda::GpuMatND*)obj;
|
||||
return (_gpuMatND.dims < 2) ? 0 : _gpuMatND.size[1];
|
||||
}
|
||||
#endif
|
||||
|
||||
return size(i).width;
|
||||
}
|
||||
|
||||
@@ -655,8 +695,13 @@ bool _InputArray::sameSize(const _InputArray& arr) const
|
||||
return false;
|
||||
sz1 = m->size();
|
||||
}
|
||||
else if ( (k1 == CUDA_GPU_MATND) && (k2 == CUDA_GPU_MATND))
|
||||
{
|
||||
return ((const cuda::GpuMatND*)obj)->size == ((const cuda::GpuMatND*)arr.obj)->size;
|
||||
}
|
||||
else
|
||||
sz1 = size();
|
||||
|
||||
if( arr.dims() > 2 )
|
||||
return false;
|
||||
return sz1 == arr.size();
|
||||
@@ -744,6 +789,12 @@ int _InputArray::dims(int i) const
|
||||
return 2;
|
||||
}
|
||||
|
||||
if( k == CUDA_GPU_MATND )
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
return ((const cuda::GpuMatND*)obj)->dims;
|
||||
}
|
||||
|
||||
if( k == CUDA_HOST_MEM )
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
@@ -799,6 +850,21 @@ size_t _InputArray::total(int i) const
|
||||
return vv[i].total();
|
||||
}
|
||||
|
||||
if( k == CUDA_GPU_MATND )
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
size_t res = 0;
|
||||
const cuda::GpuMatND& _gpuMatND = *((const cuda::GpuMatND*)obj);
|
||||
if (_gpuMatND.dims > 0)
|
||||
{
|
||||
res = 1;
|
||||
for(int d = 0 ; d<_gpuMatND.dims ; ++d)
|
||||
res *= _gpuMatND.size[d];
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return size(i).area();
|
||||
}
|
||||
|
||||
@@ -876,6 +942,9 @@ int _InputArray::type(int i) const
|
||||
if( k == CUDA_GPU_MAT )
|
||||
return ((const cuda::GpuMat*)obj)->type();
|
||||
|
||||
if( k == CUDA_GPU_MATND )
|
||||
return ((const cuda::GpuMatND*)obj)->type();
|
||||
|
||||
if( k == CUDA_HOST_MEM )
|
||||
return ((const cuda::HostMem*)obj)->type();
|
||||
|
||||
@@ -955,6 +1024,9 @@ bool _InputArray::empty() const
|
||||
return vv.empty();
|
||||
}
|
||||
|
||||
if( k == CUDA_GPU_MATND )
|
||||
return ((const cuda::GpuMatND*)obj)->empty();
|
||||
|
||||
if( k == CUDA_HOST_MEM )
|
||||
return ((const cuda::HostMem*)obj)->empty();
|
||||
|
||||
@@ -999,6 +1071,9 @@ bool _InputArray::isContinuous(int i) const
|
||||
if( k == CUDA_GPU_MAT )
|
||||
return i < 0 ? ((const cuda::GpuMat*)obj)->isContinuous() : true;
|
||||
|
||||
if( k == CUDA_GPU_MATND )
|
||||
return i < 0 ? ((const cuda::GpuMatND*)obj)->isContinuous() : true;
|
||||
|
||||
CV_Error(cv::Error::StsNotImplemented, "Unknown/unsupported array type");
|
||||
}
|
||||
|
||||
@@ -1037,6 +1112,11 @@ bool _InputArray::isSubmatrix(int i) const
|
||||
return vv[i].isSubmatrix();
|
||||
}
|
||||
|
||||
if( k == CUDA_GPU_MATND )
|
||||
{
|
||||
return ((const cuda::GpuMatND*)obj)->isSubmatrix();
|
||||
}
|
||||
|
||||
CV_Error(cv::Error::StsNotImplemented, "");
|
||||
}
|
||||
|
||||
@@ -1152,6 +1232,12 @@ size_t _InputArray::step(int i) const
|
||||
CV_Assert(i >= 0 && (size_t)i < vv.size());
|
||||
return vv[i].step;
|
||||
}
|
||||
if( k == CUDA_GPU_MATND )
|
||||
{
|
||||
const cuda::GpuMatND& _gpuMatND = *(const cuda::GpuMatND*)obj;
|
||||
CV_Assert( i >= _gpuMatND.dims );
|
||||
return _gpuMatND.step[i];
|
||||
}
|
||||
|
||||
CV_Error(Error::StsNotImplemented, "");
|
||||
}
|
||||
@@ -1234,6 +1320,18 @@ void _OutputArray::create(Size _sz, int mtype, int i, bool allowTransposed, _Out
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
if( k == CUDA_GPU_MATND && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
||||
{
|
||||
CV_Assert(!fixedSize() || ((((cuda::GpuMatND*)obj)->dims == 2) && (((cuda::GpuMatND*)obj)->size[0] == _sz.height) && (((cuda::GpuMatND*)obj)->size[1] == _sz.width)));
|
||||
CV_Assert(!fixedType() || ((cuda::GpuMatND*)obj)->type() == mtype);
|
||||
#ifdef HAVE_CUDA
|
||||
cuda::GpuMatND::SizeArray sizes = {_sz.height, _sz.width};
|
||||
((cuda::GpuMatND*)obj)->create(sizes, mtype);
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
||||
@@ -1288,6 +1386,18 @@ void _OutputArray::create(int _rows, int _cols, int mtype, int i, bool allowTran
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
if( k == CUDA_GPU_MATND && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
||||
{
|
||||
CV_Assert(!fixedSize() || ((((cuda::GpuMatND*)obj)->dims == 2) && (((cuda::GpuMatND*)obj)->size[0] == _rows) && (((cuda::GpuMatND*)obj)->size[1] == _cols)));
|
||||
CV_Assert(!fixedType() || ((cuda::GpuMatND*)obj)->type() == mtype);
|
||||
#ifdef HAVE_CUDA
|
||||
cuda::GpuMatND::SizeArray sizes = {_rows, _cols};
|
||||
((cuda::GpuMatND*)obj)->create(sizes, mtype);
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
||||
@@ -1705,6 +1815,18 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i,
|
||||
return;
|
||||
}
|
||||
|
||||
if( k == CUDA_GPU_MATND && d > 0 && i < 0 && !allowTransposed && fixedDepthMask == 0 )
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
cuda::GpuMatND::SizeArray sizeArray = cuda::GpuMatND::SizeArray(sizes, sizes+d);
|
||||
((cuda::GpuMatND*)obj)->create(sizeArray, mtype);
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
|
||||
}
|
||||
|
||||
@@ -1840,6 +1962,16 @@ void _OutputArray::release() const
|
||||
#endif
|
||||
}
|
||||
|
||||
if( k == CUDA_GPU_MATND )
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
((cuda::GpuMatND*)obj)->release();
|
||||
return;
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
|
||||
if( k == CUDA_HOST_MEM )
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
@@ -1971,6 +2103,12 @@ std::vector<cuda::GpuMat>& _OutputArray::getGpuMatVecRef() const
|
||||
CV_Assert(k == STD_VECTOR_CUDA_GPU_MAT);
|
||||
return *(std::vector<cuda::GpuMat>*)obj;
|
||||
}
|
||||
cuda::GpuMatND& _OutputArray::getGpuMatNDRef() const
|
||||
{
|
||||
_InputArray::KindFlag k = kind();
|
||||
CV_Assert( k == CUDA_GPU_MATND );
|
||||
return *(cuda::GpuMatND*)obj;
|
||||
}
|
||||
|
||||
ogl::Buffer& _OutputArray::getOGlBufferRef() const
|
||||
{
|
||||
|
||||
@@ -1164,20 +1164,31 @@ String tempfile( const char* suffix )
|
||||
fname = String(aname);
|
||||
}
|
||||
#else
|
||||
// Use GUID-based naming to avoid race condition with GetTempFileNameA
|
||||
// See issue #19648
|
||||
char temp_dir2[MAX_PATH] = { 0 };
|
||||
char temp_file[MAX_PATH] = { 0 };
|
||||
|
||||
if (temp_dir.empty())
|
||||
{
|
||||
::GetTempPathA(sizeof(temp_dir2), temp_dir2);
|
||||
temp_dir = std::string(temp_dir2);
|
||||
}
|
||||
if(0 == ::GetTempFileNameA(temp_dir.c_str(), "ocv", 0, temp_file))
|
||||
|
||||
GUID g;
|
||||
HRESULT hr = CoCreateGuid(&g);
|
||||
if (FAILED(hr))
|
||||
return String();
|
||||
char guidStr[40];
|
||||
const char* mask = "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x";
|
||||
snprintf(guidStr, sizeof(guidStr), mask,
|
||||
g.Data1, g.Data2, g.Data3, (unsigned int)g.Data4[0], (unsigned int)g.Data4[1],
|
||||
(unsigned int)g.Data4[2], (unsigned int)g.Data4[3], (unsigned int)g.Data4[4],
|
||||
(unsigned int)g.Data4[5], (unsigned int)g.Data4[6], (unsigned int)g.Data4[7]);
|
||||
|
||||
DeleteFileA(temp_file);
|
||||
|
||||
fname = temp_file;
|
||||
fname = temp_dir;
|
||||
if (!fname.empty() && fname[fname.size()-1] != '\\' && fname[fname.size()-1] != '/')
|
||||
fname += "\\";
|
||||
fname = fname + "ocv" + guidStr;
|
||||
#endif
|
||||
# else
|
||||
# ifdef __ANDROID__
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||
// generated, otherwise it may not be compatible.
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 23 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 5 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 9,
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 9 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 23,
|
||||
"Non-compatible flatbuffers version included");
|
||||
|
||||
namespace opencv_tflite {
|
||||
|
||||
@@ -1666,6 +1666,10 @@ CvWindow::CvWindow(QString name, int arg2)
|
||||
show();
|
||||
}
|
||||
|
||||
CvWindow::~CvWindow()
|
||||
{
|
||||
delete myView;
|
||||
}
|
||||
|
||||
void CvWindow::setMouseCallBack(CvMouseCallback callback, void* param)
|
||||
{
|
||||
|
||||
@@ -298,6 +298,7 @@ class CvWindow : public CvWinModel
|
||||
Q_OBJECT
|
||||
public:
|
||||
CvWindow(QString arg2, int flag = cv::WINDOW_NORMAL);
|
||||
~CvWindow();
|
||||
|
||||
void setMouseCallBack(CvMouseCallback m, void* param);
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ enum ImwriteFlags {
|
||||
IMWRITE_TIFF_PREDICTOR = 317,//!< For TIFF, use to specify predictor. See cv::ImwriteTiffPredictorFlags. Default is IMWRITE_TIFF_PREDICTOR_HORIZONTAL .
|
||||
IMWRITE_JPEG2000_COMPRESSION_X1000 = 272,//!< For JPEG2000, use to specify the target compression rate (multiplied by 1000). The value can be from 0 to 1000. Default is 1000.
|
||||
IMWRITE_AVIF_QUALITY = 512,//!< For AVIF, it can be a quality between 0 and 100 (the higher the better). Default is 95.
|
||||
IMWRITE_AVIF_DEPTH = 513,//!< For AVIF, it can be 8, 10 or 12. If >8, it is stored/read as CV_32F. Default is 8.
|
||||
IMWRITE_AVIF_DEPTH = 513,//!< For AVIF, it can be 8, 10 or 12. If >8, it is stored/read as CV_16U. Default is 8.
|
||||
IMWRITE_AVIF_SPEED = 514,//!< For AVIF, it is between 0 (slowest) and 10(fastest). Default is 9.
|
||||
IMWRITE_JPEGXL_QUALITY = 640,//!< For JPEG XL, it can be a quality from 0 to 100 (the higher is the better). Default value is 95. If set, distance parameter is re-calicurated from quality level automatically. This parameter request libjxl v0.10 or later.
|
||||
IMWRITE_JPEGXL_EFFORT = 641,//!< For JPEG XL, encoder effort/speed level without affecting decoding speed; it is between 1 (fastest) and 10 (slowest). Default is 7.
|
||||
@@ -539,6 +539,11 @@ can be saved using this function, with these exceptions:
|
||||
To achieve this, create an 8-bit 4-channel (CV_8UC4) BGRA image, ensuring the alpha channel is the last component.
|
||||
Fully transparent pixels should have an alpha value of 0, while fully opaque pixels should have an alpha value of 255.
|
||||
- 8-bit single-channel images (CV_8UC1) are not supported due to GIF's limitation to indexed color formats.
|
||||
- With AVIF encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved.
|
||||
- CV_16U images can be saved as only 10-bit or 12-bit (not 16-bit). See IMWRITE_AVIF_DEPTH.
|
||||
- AVIF images with an alpha channel can be saved using this function.
|
||||
To achieve this, create an 8-bit 4-channel (CV_8UC4) / 16-bit 4-channel (CV_16UC4) BGRA image, ensuring the alpha channel is the last component.
|
||||
Fully transparent pixels should have an alpha value of 0, while fully opaque pixels should have an alpha value of 255 (8-bit) / 1023 (10-bit) / 4095 (12-bit) (see the code sample below).
|
||||
|
||||
If the image format is not supported, the image will be converted to 8-bit unsigned (CV_8U) and saved that way.
|
||||
|
||||
|
||||
@@ -86,15 +86,12 @@ AvifImageUniquePtr ConvertToAvif(const cv::Mat &img, bool lossless, int bit_dept
|
||||
result->yuvFormat = AVIF_PIXEL_FORMAT_YUV400;
|
||||
result->colorPrimaries = AVIF_COLOR_PRIMARIES_UNSPECIFIED;
|
||||
result->transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED;
|
||||
result->matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_IDENTITY;
|
||||
result->matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED;
|
||||
result->yuvRange = AVIF_RANGE_FULL;
|
||||
result->yuvPlanes[0] = img.data;
|
||||
result->yuvRowBytes[0] = img.step[0];
|
||||
result->imageOwnsYUVPlanes = AVIF_FALSE;
|
||||
return AvifImageUniquePtr(result);
|
||||
}
|
||||
|
||||
if (lossless) {
|
||||
} else if (lossless) {
|
||||
result =
|
||||
avifImageCreate(width, height, bit_depth, AVIF_PIXEL_FORMAT_YUV444);
|
||||
if (result == nullptr) return nullptr;
|
||||
@@ -139,22 +136,24 @@ AvifImageUniquePtr ConvertToAvif(const cv::Mat &img, bool lossless, int bit_dept
|
||||
#endif
|
||||
}
|
||||
|
||||
avifRGBImage rgba;
|
||||
avifRGBImageSetDefaults(&rgba, result);
|
||||
if (img.channels() == 3) {
|
||||
rgba.format = AVIF_RGB_FORMAT_BGR;
|
||||
} else {
|
||||
CV_Assert(img.channels() == 4);
|
||||
rgba.format = AVIF_RGB_FORMAT_BGRA;
|
||||
}
|
||||
rgba.rowBytes = (uint32_t)img.step[0];
|
||||
rgba.depth = bit_depth;
|
||||
rgba.pixels =
|
||||
const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(img.data));
|
||||
if (img.channels() > 1) {
|
||||
avifRGBImage rgba;
|
||||
avifRGBImageSetDefaults(&rgba, result);
|
||||
if (img.channels() == 3) {
|
||||
rgba.format = AVIF_RGB_FORMAT_BGR;
|
||||
} else {
|
||||
CV_Assert(img.channels() == 4);
|
||||
rgba.format = AVIF_RGB_FORMAT_BGRA;
|
||||
}
|
||||
rgba.rowBytes = (uint32_t)img.step[0];
|
||||
rgba.depth = bit_depth;
|
||||
rgba.pixels =
|
||||
const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(img.data));
|
||||
|
||||
if (avifImageRGBToYUV(result, &rgba) != AVIF_RESULT_OK) {
|
||||
avifImageDestroy(result);
|
||||
return nullptr;
|
||||
if (avifImageRGBToYUV(result, &rgba) != AVIF_RESULT_OK) {
|
||||
avifImageDestroy(result);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return AvifImageUniquePtr(result);
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ bool BmpDecoder::readData( Mat& img )
|
||||
}
|
||||
else
|
||||
{
|
||||
int x_shift3 = (int)(line_end - data);
|
||||
ptrdiff_t x_shift3 = line_end - data;
|
||||
|
||||
if( code == 2 )
|
||||
{
|
||||
@@ -430,7 +430,7 @@ decode_rle4_bad: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
int x_shift3 = (int)(line_end - data);
|
||||
ptrdiff_t x_shift3 = line_end - data;
|
||||
int y_shift = m_height - y;
|
||||
|
||||
if( code || !line_end_flag || x_shift3 < width3 )
|
||||
@@ -441,7 +441,7 @@ decode_rle4_bad: ;
|
||||
y_shift = m_strm.getByte();
|
||||
}
|
||||
|
||||
x_shift3 += (y_shift * width3) & ((code == 0) - 1);
|
||||
x_shift3 += ((ptrdiff_t)y_shift * width3) & ((code == 0) - 1);
|
||||
|
||||
if( y >= m_height )
|
||||
break;
|
||||
|
||||
@@ -435,7 +435,7 @@ bool IsColorPalette( PaletteEntry* palette, int bpp )
|
||||
uchar* FillUniColor( uchar* data, uchar*& line_end,
|
||||
int step, int width3,
|
||||
int& y, int height,
|
||||
int count3, PaletteEntry clr )
|
||||
ptrdiff_t count3, PaletteEntry clr )
|
||||
{
|
||||
do
|
||||
{
|
||||
@@ -444,7 +444,7 @@ uchar* FillUniColor( uchar* data, uchar*& line_end,
|
||||
if( end > line_end )
|
||||
end = line_end;
|
||||
|
||||
count3 -= (int)(end - data);
|
||||
count3 -= end - data;
|
||||
|
||||
for( ; data < end; data += 3 )
|
||||
{
|
||||
@@ -467,7 +467,7 @@ uchar* FillUniColor( uchar* data, uchar*& line_end,
|
||||
uchar* FillUniGray( uchar* data, uchar*& line_end,
|
||||
int step, int width,
|
||||
int& y, int height,
|
||||
int count, uchar clr )
|
||||
ptrdiff_t count, uchar clr )
|
||||
{
|
||||
do
|
||||
{
|
||||
@@ -476,7 +476,7 @@ uchar* FillUniGray( uchar* data, uchar*& line_end,
|
||||
if( end > line_end )
|
||||
end = line_end;
|
||||
|
||||
count -= (int)(end - data);
|
||||
count -= end - data;
|
||||
|
||||
for( ; data < end; data++ )
|
||||
{
|
||||
|
||||
@@ -124,9 +124,9 @@ void FillGrayPalette( PaletteEntry* palette, int bpp, bool negative = false );
|
||||
bool IsColorPalette( PaletteEntry* palette, int bpp );
|
||||
void CvtPaletteToGray( const PaletteEntry* palette, uchar* grayPalette, int entries );
|
||||
uchar* FillUniColor( uchar* data, uchar*& line_end, int step, int width3,
|
||||
int& y, int height, int count3, PaletteEntry clr );
|
||||
int& y, int height, ptrdiff_t count3, PaletteEntry clr );
|
||||
uchar* FillUniGray( uchar* data, uchar*& line_end, int step, int width3,
|
||||
int& y, int height, int count3, uchar clr );
|
||||
int& y, int height, ptrdiff_t count3, uchar clr );
|
||||
|
||||
uchar* FillColorRow8( uchar* data, uchar* indices, int len, PaletteEntry* palette );
|
||||
uchar* FillGrayRow8( uchar* data, uchar* indices, int len, uchar* palette );
|
||||
|
||||
@@ -296,13 +296,15 @@ INSTANTIATE_TEST_CASE_P(Imgcodecs, Exif,
|
||||
testing::ValuesIn(exif_files));
|
||||
|
||||
#ifdef HAVE_AVIF
|
||||
TEST(Imgcodecs_Avif, ReadWriteWithExif)
|
||||
typedef testing::TestWithParam<int> MatChannels;
|
||||
|
||||
TEST_P(MatChannels, Imgcodecs_Avif_ReadWriteWithExif)
|
||||
{
|
||||
int avif_nbits = 10;
|
||||
int avif_speed = 10;
|
||||
int avif_quality = 85;
|
||||
int imgdepth = avif_nbits > 8 ? CV_16U : CV_8U;
|
||||
int imgtype = CV_MAKETYPE(imgdepth, 3);
|
||||
int imgtype = CV_MAKETYPE(imgdepth, GetParam());
|
||||
const string outputname = cv::tempfile(".avif");
|
||||
Mat img = makeCirclesImage(Size(1280, 720), imgtype, avif_nbits);
|
||||
|
||||
@@ -328,7 +330,7 @@ TEST(Imgcodecs_Avif, ReadWriteWithExif)
|
||||
EXPECT_EQ(img2.rows, img.rows);
|
||||
EXPECT_EQ(img2.type(), imgtype);
|
||||
EXPECT_EQ(read_metadata_types, read_metadata_types2);
|
||||
EXPECT_GE(read_metadata_types.size(), 1u);
|
||||
ASSERT_GE(read_metadata_types.size(), 1u);
|
||||
EXPECT_EQ(read_metadata, read_metadata2);
|
||||
EXPECT_EQ(read_metadata_types[0], IMAGE_METADATA_EXIF);
|
||||
EXPECT_EQ(read_metadata_types.size(), read_metadata.size());
|
||||
@@ -338,6 +340,9 @@ TEST(Imgcodecs_Avif, ReadWriteWithExif)
|
||||
EXPECT_LT(mse, 1500);
|
||||
remove(outputname.c_str());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Imgcodecs, MatChannels,
|
||||
testing::Values(1,3,4));
|
||||
#endif // HAVE_AVIF
|
||||
|
||||
#ifdef HAVE_WEBP
|
||||
|
||||
@@ -1344,8 +1344,8 @@ public class ImgprocTest extends OpenCVTestCase {
|
||||
|
||||
RotatedRect rrect = Imgproc.minAreaRect(points);
|
||||
|
||||
assertEquals(new Size(5, 2), rrect.size);
|
||||
assertEquals(0., rrect.angle);
|
||||
assertEquals(new Size(2, 5), rrect.size);
|
||||
assertEquals(-90., rrect.angle);
|
||||
assertEquals(new Point(3.5, 2), rrect.center);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,12 +76,16 @@ static int Sklansky_( Point_<_Tp>** array, int start, int end, int* stack, int n
|
||||
|
||||
if( CV_SIGN( by ) != nsign )
|
||||
{
|
||||
_Tp ax = array[pcur]->x - array[pprev]->x;
|
||||
_Tp bx = array[pnext]->x - array[pcur]->x;
|
||||
_Tp ay = cury - array[pprev]->y;
|
||||
_DotTp convexity = (_DotTp)ay*bx - (_DotTp)ax*by; // if >0 then convex angle
|
||||
Vec<_Tp, 2> a(array[pcur]->x - array[pprev]->x, cury - array[pprev]->y);
|
||||
Vec<_Tp, 2> b(array[pnext]->x - array[pcur]->x, by);
|
||||
if (std::is_floating_point<_Tp>::value)
|
||||
{
|
||||
a = normalize(a);
|
||||
b = normalize(b);
|
||||
}
|
||||
_DotTp convexity = (_DotTp)a[1]*b[0] - (_DotTp)a[0]*b[1]; // if >0 then convex angle
|
||||
|
||||
if( CV_SIGN( convexity ) == sign2 && (ax != 0 || ay != 0) )
|
||||
if( CV_SIGN( convexity ) == sign2 && (a[0] != 0 || a[1] != 0) )
|
||||
{
|
||||
pprev = pcur;
|
||||
pcur = pnext;
|
||||
|
||||
@@ -1174,13 +1174,31 @@ static bool replacementFilter2D(int stype, int dtype, int kernel_type,
|
||||
cvhalFilter2D* ctx;
|
||||
int res = cv_hal_filterInit(&ctx, kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, width, height,
|
||||
stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, src_data == dst_data);
|
||||
if (res != CV_HAL_ERROR_OK)
|
||||
if (res == CV_HAL_ERROR_NOT_IMPLEMENTED)
|
||||
{
|
||||
return false;
|
||||
} else if (res != CV_HAL_ERROR_OK)
|
||||
{
|
||||
CV_Error_(cv::Error::StsInternal,
|
||||
("HAL implementation filterInit ==> " CVAUX_STR(cv_hal_filterInit) " returned %d (0x%08x)", res, res));
|
||||
}
|
||||
|
||||
res = cv_hal_filter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y);
|
||||
bool success = (res == CV_HAL_ERROR_OK);
|
||||
if (res != CV_HAL_ERROR_OK && res != CV_HAL_ERROR_NOT_IMPLEMENTED )
|
||||
{
|
||||
CV_Error_(cv::Error::StsInternal,
|
||||
("HAL implementation filter ==> " CVAUX_STR(cv_hal_filter) " returned %d (0x%08x)", res, res));
|
||||
}
|
||||
|
||||
res = cv_hal_filterFree(ctx);
|
||||
if (res != CV_HAL_ERROR_OK)
|
||||
return false;
|
||||
success &= (res == CV_HAL_ERROR_OK);
|
||||
if (res != CV_HAL_ERROR_OK && res != CV_HAL_ERROR_NOT_IMPLEMENTED )
|
||||
{
|
||||
CV_Error_(cv::Error::StsInternal,
|
||||
("HAL implementation filterFree ==> " CVAUX_STR(cv_hal_filterFree) " returned %d (0x%08x)", res, res));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -1372,13 +1390,31 @@ static bool replacementSepFilter(int stype, int dtype, int ktype,
|
||||
kernelx_data, kernelx_len,
|
||||
kernely_data, kernely_len,
|
||||
anchor_x, anchor_y, delta, borderType);
|
||||
if (res != CV_HAL_ERROR_OK)
|
||||
if (res == CV_HAL_ERROR_NOT_IMPLEMENTED)
|
||||
{
|
||||
return false;
|
||||
} else if (res != CV_HAL_ERROR_OK)
|
||||
{
|
||||
CV_Error_(cv::Error::StsInternal,
|
||||
("HAL implementation sepFilterInit ==> " CVAUX_STR(cv_hal_sepFilterInit) " returned %d (0x%08x)", res, res));
|
||||
}
|
||||
|
||||
res = cv_hal_sepFilter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y);
|
||||
bool success = (res == CV_HAL_ERROR_OK);
|
||||
if (res != CV_HAL_ERROR_OK && res != CV_HAL_ERROR_NOT_IMPLEMENTED )
|
||||
{
|
||||
CV_Error_(cv::Error::StsInternal,
|
||||
("HAL implementation sepFilter ==> " CVAUX_STR(cv_hal_sepFilter) " returned %d (0x%08x)", res, res));
|
||||
}
|
||||
|
||||
res = cv_hal_sepFilterFree(ctx);
|
||||
if (res != CV_HAL_ERROR_OK)
|
||||
return false;
|
||||
success &= (res == CV_HAL_ERROR_OK);
|
||||
if (res != CV_HAL_ERROR_OK && res != CV_HAL_ERROR_NOT_IMPLEMENTED )
|
||||
{
|
||||
CV_Error_(cv::Error::StsInternal,
|
||||
("HAL implementation sepFilterFree ==> " CVAUX_STR(cv_hal_sepFilterFree) " returned %d (0x%08x)", res, res));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
@@ -218,8 +218,14 @@ static bool halMorph(int op, int src_type, int dst_type,
|
||||
anchor_x, anchor_y,
|
||||
borderType, borderValue,
|
||||
iterations, isSubmatrix, src_data == dst_data);
|
||||
if (res != CV_HAL_ERROR_OK)
|
||||
if (res == CV_HAL_ERROR_NOT_IMPLEMENTED)
|
||||
{
|
||||
return false;
|
||||
} else if (res != CV_HAL_ERROR_OK)
|
||||
{
|
||||
CV_Error_(cv::Error::StsInternal,
|
||||
("HAL implementation morphInit ==> " CVAUX_STR(cv_hal_morphInit) " returned %d (0x%08x)", res, res));
|
||||
}
|
||||
|
||||
res = cv_hal_morph(ctx, src_data, src_step, dst_data, dst_step, width, height,
|
||||
roi_width, roi_height,
|
||||
@@ -227,10 +233,19 @@ static bool halMorph(int op, int src_type, int dst_type,
|
||||
roi_width2, roi_height2,
|
||||
roi_x2, roi_y2);
|
||||
bool success = (res == CV_HAL_ERROR_OK);
|
||||
if (res != CV_HAL_ERROR_OK && res != CV_HAL_ERROR_NOT_IMPLEMENTED )
|
||||
{
|
||||
CV_Error_(cv::Error::StsInternal,
|
||||
("HAL implementation morph ==> " CVAUX_STR(cv_hal_morph) " returned %d (0x%08x)", res, res));
|
||||
}
|
||||
|
||||
res = cv_hal_morphFree(ctx);
|
||||
if (res != CV_HAL_ERROR_OK)
|
||||
return false;
|
||||
success &= (res == CV_HAL_ERROR_OK);
|
||||
if (res != CV_HAL_ERROR_OK && res != CV_HAL_ERROR_NOT_IMPLEMENTED )
|
||||
{
|
||||
CV_Error_(cv::Error::StsInternal,
|
||||
("HAL implementation morphFree ==> " CVAUX_STR(cv_hal_morphFree) " returned %d (0x%08x)", res, res));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ enum { CALIPERS_MAXHEIGHT=0, CALIPERS_MINAREARECT=1, CALIPERS_MAXDIST=2 };
|
||||
// Parameters:
|
||||
// points - convex hull vertices ( any orientation )
|
||||
// n - number of vertices
|
||||
// orientation - -1 for clockwise vertices order, 1 for CCW. 0 if unknown.
|
||||
// mode - concrete application of algorithm
|
||||
// can be CV_CALIPERS_MAXDIST or
|
||||
// CV_CALIPERS_MINAREARECT
|
||||
@@ -115,7 +116,7 @@ static bool firstVecIsRight(const cv::Point2f& vec1, const cv::Point2f &vec2)
|
||||
}
|
||||
|
||||
/* we will use usual cartesian coordinates */
|
||||
static void rotatingCalipers( const Point2f* points, int n, int mode, float* out )
|
||||
static void rotatingCalipers( const Point2f* points, int n, float orientation, int mode, float* out )
|
||||
{
|
||||
float minarea = FLT_MAX;
|
||||
float max_dist = 0;
|
||||
@@ -132,7 +133,6 @@ static void rotatingCalipers( const Point2f* points, int n, int mode, float* out
|
||||
(a,b) (-b,a) (-a,-b) (b, -a)
|
||||
*/
|
||||
/* this is a first base vector (a,b) initialized by (1,0) */
|
||||
float orientation = 0;
|
||||
float base_a;
|
||||
float base_b = 0;
|
||||
|
||||
@@ -171,6 +171,7 @@ static void rotatingCalipers( const Point2f* points, int n, int mode, float* out
|
||||
}
|
||||
|
||||
// find convex hull orientation
|
||||
if (orientation == 0.f)
|
||||
{
|
||||
double ax = vect[n-1].x;
|
||||
double ay = vect[n-1].y;
|
||||
@@ -364,8 +365,10 @@ cv::RotatedRect cv::minAreaRect( InputArray _points )
|
||||
Mat hull;
|
||||
Point2f out[3];
|
||||
RotatedRect box;
|
||||
box.angle = -(float)CV_PI / 2; // default angle for box without rotation and single point
|
||||
|
||||
convexHull(_points, hull, false, true);
|
||||
static const bool clockwise = false;
|
||||
convexHull(_points, hull, clockwise, true);
|
||||
|
||||
if( hull.depth() != CV_32F )
|
||||
{
|
||||
@@ -379,22 +382,37 @@ cv::RotatedRect cv::minAreaRect( InputArray _points )
|
||||
|
||||
if( n > 2 )
|
||||
{
|
||||
rotatingCalipers( hpoints, n, CALIPERS_MINAREARECT, (float*)out );
|
||||
rotatingCalipers( hpoints, n, clockwise ? -1.f : 1.f, CALIPERS_MINAREARECT, (float*)out );
|
||||
box.center.x = out[0].x + (out[1].x + out[2].x)*0.5f;
|
||||
box.center.y = out[0].y + (out[1].y + out[2].y)*0.5f;
|
||||
box.size.width = (float)std::sqrt((double)out[1].x*out[1].x + (double)out[1].y*out[1].y);
|
||||
box.size.height = (float)std::sqrt((double)out[2].x*out[2].x + (double)out[2].y*out[2].y);
|
||||
box.angle = (float)atan2( (double)out[1].y, (double)out[1].x );
|
||||
box.size.width = (float)std::sqrt((double)out[2].x*out[2].x + (double)out[2].y*out[2].y);
|
||||
box.size.height = (float)std::sqrt((double)out[1].x*out[1].x + (double)out[1].y*out[1].y);
|
||||
if (out[1].x == 0.f && out[1].y > 0.f)
|
||||
std::swap(box.size.width, box.size.height);
|
||||
else
|
||||
box.angle += (float)atan2( (double)out[1].y, (double)out[1].x );
|
||||
}
|
||||
else if( n == 2 )
|
||||
{
|
||||
box.center.x = (hpoints[0].x + hpoints[1].x)*0.5f;
|
||||
box.center.y = (hpoints[0].y + hpoints[1].y)*0.5f;
|
||||
double dx = hpoints[1].x - hpoints[0].x;
|
||||
double dy = hpoints[1].y - hpoints[0].y;
|
||||
box.size.width = (float)std::sqrt(dx*dx + dy*dy);
|
||||
box.size.height = 0;
|
||||
box.angle = (float)atan2( dy, dx );
|
||||
double dx = hpoints[0].x - hpoints[1].x;
|
||||
double dy = hpoints[0].y - hpoints[1].y;
|
||||
box.size.width = 0;
|
||||
box.size.height = (float)std::sqrt(dx*dx + dy*dy);
|
||||
if (dx == 0)
|
||||
{
|
||||
std::swap(box.size.width, box.size.height);
|
||||
}
|
||||
else if (dy < 0)
|
||||
{
|
||||
box.angle = (float)atan2( dy, dx );
|
||||
std::swap(box.size.width, box.size.height);
|
||||
}
|
||||
else if (dy > 0)
|
||||
{
|
||||
box.angle += (float)atan2( dy, dx );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -403,6 +421,8 @@ cv::RotatedRect cv::minAreaRect( InputArray _points )
|
||||
}
|
||||
|
||||
box.angle = (float)(box.angle*180/CV_PI);
|
||||
CV_DbgCheckGE(box.angle, -90.0f, "");
|
||||
CV_DbgCheckLT(box.angle, 0.0f, "");
|
||||
return box;
|
||||
}
|
||||
|
||||
|
||||
@@ -1232,6 +1232,57 @@ TEST(minEnclosingPolygon, pentagon)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgproc_minAreaRect, reproducer_21482)
|
||||
{
|
||||
const int N = 4;
|
||||
float pts_[N][2] = {
|
||||
{ 188.8991f, 12.400669f },
|
||||
{ 80.64467f, -49.644814f },
|
||||
{ 469.59897f, 173.28242f },
|
||||
{ 690.4597f, 299.86768f },
|
||||
};
|
||||
|
||||
Mat contour(N, 1, CV_32FC2, (void*)pts_);
|
||||
|
||||
RotatedRect rr = cv::minAreaRect(contour);
|
||||
|
||||
EXPECT_TRUE(checkMinAreaRect(rr, contour)) << rr.center << " " << rr.size << " " << rr.angle;
|
||||
EXPECT_NEAR(min(rr.size.width, rr.size.height), 0, 1e-5);
|
||||
EXPECT_GE(max(rr.size.width, rr.size.height), 702);
|
||||
}
|
||||
|
||||
TEST(Imgproc_minAreaRect, reproducer_21482_small_values)
|
||||
{
|
||||
const int N = 4;
|
||||
float pts_[N][2] = { { 0.f, 0.f }, { 1e-4f, 0.f }, { 1e-4f, 1e-4f }, { 0.f, 1e-4f },};
|
||||
|
||||
Mat contour(N, 1, CV_32FC2, (void*)pts_);
|
||||
|
||||
RotatedRect rr = cv::minAreaRect(contour);
|
||||
|
||||
EXPECT_TRUE(checkMinAreaRect(rr, contour)) << rr.center << " " << rr.size << " " << rr.angle;
|
||||
EXPECT_EQ(rr.size.width, 1e-4f);
|
||||
EXPECT_EQ(rr.size.height, 1e-4f);
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<tuple<Point2f, Point2f, Point2f, Size2f, float>> minAreaRect_of_line;
|
||||
TEST_P(minAreaRect_of_line, accuracy)
|
||||
{
|
||||
Point2f p1 = get<0>(GetParam());
|
||||
Point2f p2 = get<1>(GetParam());
|
||||
RotatedRect out = minAreaRect(std::vector<Point2f>{p1, p2});
|
||||
EXPECT_EQ(out.center, get<2>(GetParam()));
|
||||
EXPECT_EQ(out.size, get<3>(GetParam()));
|
||||
EXPECT_NEAR(out.angle, get<4>(GetParam()), 1e-6);
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(Imgproc, minAreaRect_of_line,
|
||||
testing::Values(
|
||||
std::make_tuple(Point2f(10, 15), Point2f(10, 25), Point2f(10, 20), Size2f(10, 0), -90.f),
|
||||
std::make_tuple(Point2f(450, 500), Point2f(508, 500), Point2f(479, 500), Size2f(0, 58), -90.f),
|
||||
std::make_tuple(Point2f(10, 20), Point2f(13, 16), Point2f(11.5, 18), Size2f(5, 0), -53.1301002f),
|
||||
std::make_tuple(Point2f(9, 19), Point2f(4, 7), Point2f(6.5, 13), Size2f(0, 13), -22.6198654f)
|
||||
));
|
||||
|
||||
}} // namespace
|
||||
|
||||
/* End of file. */
|
||||
|
||||
@@ -710,14 +710,14 @@ QUnit.test('test_rotatedRectangleIntersection', function(assert) {
|
||||
assert.deepEqual(intersectionType, cv.INTERSECT_FULL);
|
||||
intersectionPoints.convertTo(intersectionPoints, cv.CV_32S);
|
||||
let intersectionPointsData = intersectionPoints.data32S;
|
||||
assert.deepEqual(intersectionPointsData[0], 30);
|
||||
assert.deepEqual(intersectionPointsData[1], 40);
|
||||
assert.deepEqual(intersectionPointsData[2], 40);
|
||||
assert.deepEqual(intersectionPointsData[3], 30);
|
||||
assert.deepEqual(intersectionPointsData[4], 50);
|
||||
assert.deepEqual(intersectionPointsData[5], 40);
|
||||
assert.deepEqual(intersectionPointsData[6], 40);
|
||||
assert.deepEqual(intersectionPointsData[7], 50);
|
||||
assert.deepEqual(intersectionPointsData[0], 40);
|
||||
assert.deepEqual(intersectionPointsData[1], 50);
|
||||
assert.deepEqual(intersectionPointsData[2], 30);
|
||||
assert.deepEqual(intersectionPointsData[3], 40);
|
||||
assert.deepEqual(intersectionPointsData[4], 40);
|
||||
assert.deepEqual(intersectionPointsData[5], 30);
|
||||
assert.deepEqual(intersectionPointsData[6], 50);
|
||||
assert.deepEqual(intersectionPointsData[7], 40);
|
||||
|
||||
intersectionType = cv.rotatedRectangleIntersection(rr1, rr3, intersectionPoints);
|
||||
|
||||
|
||||
@@ -5,5 +5,5 @@ import sys
|
||||
if sys.version_info[:2] >= (3, 0):
|
||||
def exec_file_wrapper(fpath, g_vars, l_vars):
|
||||
with open(fpath) as f:
|
||||
code = compile(f.read(), os.path.basename(fpath), 'exec')
|
||||
code = compile(f.read(), fpath, 'exec')
|
||||
exec(code, g_vars, l_vars)
|
||||
|
||||
@@ -714,28 +714,29 @@ bool pyopencv_to(PyObject* obj, String &value, const ArgInfo& info)
|
||||
std::string str;
|
||||
|
||||
#if ((PY_VERSION_HEX >= 0x03060000) && !defined(Py_LIMITED_API)) || (Py_LIMITED_API >= 0x03060000)
|
||||
PyObject* path_obj = NULL;
|
||||
if (info.pathlike)
|
||||
{
|
||||
obj = PyOS_FSPath(obj);
|
||||
path_obj = PyOS_FSPath(obj);
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
failmsg("Expected '%s' to be a str or path-like object", info.name);
|
||||
return false;
|
||||
}
|
||||
obj = path_obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool result = false;
|
||||
if (getUnicodeString(obj, str))
|
||||
{
|
||||
value = str;
|
||||
return true;
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If error hasn't been already set by Python conversion functions
|
||||
if (!PyErr_Occurred())
|
||||
{
|
||||
// Direct access to underlying slots of PyObjectType is not allowed
|
||||
// when limited API is enabled
|
||||
#ifdef Py_LIMITED_API
|
||||
failmsg("Can't convert object to 'str' for '%s'", info.name);
|
||||
#else
|
||||
@@ -744,7 +745,12 @@ bool pyopencv_to(PyObject* obj, String &value, const ArgInfo& info)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
#if ((PY_VERSION_HEX >= 0x03060000) && !defined(Py_LIMITED_API)) || (Py_LIMITED_API >= 0x03060000)
|
||||
Py_XDECREF(path_obj);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
||||
@@ -81,7 +81,7 @@ class Hackathon244Tests(NewOpenCVTests):
|
||||
mc, mr = cv.minEnclosingCircle(a)
|
||||
|
||||
be0 = ((150.2511749267578, 150.77322387695312), (158.024658203125, 197.57696533203125), 37.57804489135742)
|
||||
br0 = ((161.2974090576172, 154.41793823242188), (207.7177734375, 199.2301483154297), 80.83544921875)
|
||||
br0 = ((161.2974090576172, 154.41793823242188), (199.2301483154297, 207.7177734375), -9.164555549621582)
|
||||
mc0, mr0 = (160.41790771484375, 144.55152893066406), 136.713500977
|
||||
|
||||
self.check_close_boxes(be, be0, 5, 15)
|
||||
|
||||
@@ -277,6 +277,9 @@ void MultiBandBlender::prepare(Rect dst_roi)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
dst_pyr_laplace_.clear();
|
||||
dst_band_weights_.clear();
|
||||
|
||||
dst_pyr_laplace_.resize(num_bands_ + 1);
|
||||
dst_pyr_laplace_[0] = dst_;
|
||||
|
||||
|
||||
@@ -383,6 +383,51 @@ double findTransformECC(InputArray templateImage, InputArray inputImage,
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 50, 0.001),
|
||||
InputArray inputMask = noArray());
|
||||
|
||||
/** @brief Finds the geometric transform (warp) between two images in terms of the ECC criterion @cite EP08
|
||||
using validity masks for both the template and the input images.
|
||||
|
||||
This function extends findTransformECC() by adding a mask for the template image.
|
||||
The Enhanced Correlation Coefficient is evaluated only over pixels that are valid in both images:
|
||||
on each iteration inputMask is warped into the template frame and combined with templateMask, and
|
||||
only the intersection of these masks contributes to the objective function.
|
||||
|
||||
@param templateImage 1 or 3 channel template image; CV_8U, CV_16U, CV_32F, CV_64F type.
|
||||
@param inputImage input image which should be warped with the final warpMatrix in
|
||||
order to provide an image similar to templateImage, same type as templateImage.
|
||||
@param templateMask single-channel 8-bit mask for templateImage indicating valid pixels
|
||||
to be used in the alignment. Must have the same size as templateImage.
|
||||
@param inputMask single-channel 8-bit mask for inputImage indicating valid pixels
|
||||
before warping. Must have the same size as inputImage.
|
||||
@param warpMatrix floating-point \f$2\times 3\f$ or \f$3\times 3\f$ mapping matrix (warp).
|
||||
@param motionType parameter, specifying the type of motion:
|
||||
- **MOTION_TRANSLATION** sets a translational motion model; warpMatrix is \f$2\times 3\f$ with
|
||||
the first \f$2\times 2\f$ part being the unity matrix and the rest two parameters being
|
||||
estimated.
|
||||
- **MOTION_EUCLIDEAN** sets a Euclidean (rigid) transformation as motion model; three
|
||||
parameters are estimated; warpMatrix is \f$2\times 3\f$.
|
||||
- **MOTION_AFFINE** sets an affine motion model (DEFAULT); six parameters are estimated;
|
||||
warpMatrix is \f$2\times 3\f$.
|
||||
- **MOTION_HOMOGRAPHY** sets a homography as a motion model; eight parameters are
|
||||
estimated; warpMatrix is \f$3\times 3\f$.
|
||||
@param criteria parameter, specifying the termination criteria of the ECC algorithm;
|
||||
criteria.epsilon defines the threshold of the increment in the correlation coefficient between two
|
||||
iterations (a negative criteria.epsilon makes criteria.maxcount the only termination criterion).
|
||||
Default values are shown in the declaration above.
|
||||
@param gaussFiltSize size of the Gaussian blur filter used for smoothing images and masks
|
||||
before computing the alignment (DEFAULT: 5).
|
||||
|
||||
@sa
|
||||
findTransformECC, computeECC, estimateAffine2D, estimateAffinePartial2D, findHomography
|
||||
*/
|
||||
CV_EXPORTS_W double findTransformECCWithMask( InputArray templateImage,
|
||||
InputArray inputImage,
|
||||
InputArray templateMask,
|
||||
InputArray inputMask,
|
||||
InputOutputArray warpMatrix,
|
||||
int motionType = MOTION_AFFINE,
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 50, 1e-6),
|
||||
int gaussFiltSize = 5 );
|
||||
|
||||
/** @example samples/cpp/snippets/kalman.cpp
|
||||
An example using the standard Kalman filter
|
||||
*/
|
||||
|
||||
+72
-25
@@ -333,8 +333,15 @@ double cv::computeECC(InputArray templateImage, InputArray inputImage, InputArra
|
||||
return templateImage_zeromean.dot(inputImage_zeromean) / (templateImagenorm * inputImagenorm);
|
||||
}
|
||||
|
||||
double cv::findTransformECC(InputArray templateImage, InputArray inputImage, InputOutputArray warpMatrix,
|
||||
int motionType, TermCriteria criteria, InputArray inputMask, int gaussFiltSize) {
|
||||
|
||||
double cv::findTransformECCWithMask( InputArray templateImage,
|
||||
InputArray inputImage,
|
||||
InputArray templateMask,
|
||||
InputArray inputMask,
|
||||
InputOutputArray warpMatrix,
|
||||
int motionType,
|
||||
TermCriteria criteria,
|
||||
int gaussFiltSize) {
|
||||
Mat src = templateImage.getMat(); // template image
|
||||
Mat dst = inputImage.getMat(); // input image (to be warped)
|
||||
Mat map = warpMatrix.getMat(); // warp (transformation)
|
||||
@@ -416,7 +423,7 @@ double cv::findTransformECC(InputArray templateImage, InputArray inputImage, Inp
|
||||
Ycoord.release();
|
||||
|
||||
const int channels = src.channels();
|
||||
int type = CV_MAKETYPE(CV_32F, channels); // используем отдельно, если нужно явно
|
||||
int type = CV_MAKETYPE(CV_32F, channels);
|
||||
|
||||
std::vector<cv::Mat> XgridCh(channels, Xgrid);
|
||||
cv::merge(XgridCh, Xgrid);
|
||||
@@ -430,27 +437,10 @@ double cv::findTransformECC(InputArray templateImage, InputArray inputImage, Inp
|
||||
Mat imageWarped = Mat(hs, ws, type); // to store the warped zero-mean input image
|
||||
Mat imageMask = Mat(hs, ws, CV_8U); // to store the final mask
|
||||
|
||||
Mat inputMaskMat = inputMask.getMat();
|
||||
// to use it for mask warping
|
||||
Mat preMask;
|
||||
if (inputMask.empty())
|
||||
preMask = Mat::ones(hd, wd, CV_8U);
|
||||
else
|
||||
threshold(inputMask, preMask, 0, 1, THRESH_BINARY);
|
||||
|
||||
// Gaussian filtering is optional
|
||||
src.convertTo(templateFloat, templateFloat.type());
|
||||
GaussianBlur(templateFloat, templateFloat, Size(gaussFiltSize, gaussFiltSize), 0, 0);
|
||||
|
||||
Mat preMaskFloat;
|
||||
preMask.convertTo(preMaskFloat, type);
|
||||
GaussianBlur(preMaskFloat, preMaskFloat, Size(gaussFiltSize, gaussFiltSize), 0, 0);
|
||||
// Change threshold.
|
||||
preMaskFloat *= (0.5 / 0.95);
|
||||
// Rounding conversion.
|
||||
preMaskFloat.convertTo(preMask, preMask.type());
|
||||
preMask.convertTo(preMaskFloat, preMaskFloat.type());
|
||||
|
||||
dst.convertTo(imageFloat, imageFloat.type());
|
||||
GaussianBlur(imageFloat, imageFloat, Size(gaussFiltSize, gaussFiltSize), 0, 0);
|
||||
|
||||
@@ -466,12 +456,48 @@ double cv::findTransformECC(InputArray templateImage, InputArray inputImage, Inp
|
||||
filter2D(imageFloat, gradientX, -1, dx);
|
||||
filter2D(imageFloat, gradientY, -1, dx.t());
|
||||
|
||||
cv::Mat preMaskFloatNCh;
|
||||
std::vector<cv::Mat> maskChannels(gradientX.channels(), preMaskFloat);
|
||||
cv::merge(maskChannels, preMaskFloatNCh);
|
||||
// To use in mask warping
|
||||
Mat templtMask;
|
||||
if(templateMask.empty())
|
||||
{
|
||||
templtMask = Mat::ones(hs, ws, CV_8U);
|
||||
}
|
||||
else
|
||||
{
|
||||
threshold(templateMask, templtMask, 0, 1, THRESH_BINARY);
|
||||
templtMask.convertTo(templtMask, CV_32F);
|
||||
GaussianBlur(templtMask, templtMask, Size(gaussFiltSize, gaussFiltSize), 0, 0);
|
||||
templtMask *= (0.5/0.95);
|
||||
templtMask.convertTo(templtMask, CV_8U);
|
||||
}
|
||||
|
||||
gradientX = gradientX.mul(preMaskFloatNCh);
|
||||
gradientY = gradientY.mul(preMaskFloatNCh);
|
||||
//to use it for mask warping
|
||||
Mat preMask;
|
||||
if(inputMask.empty())
|
||||
{
|
||||
preMask = Mat::ones(hd, wd, CV_8U);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat preMaskFloat;
|
||||
threshold(inputMask, preMask, 0, 1, THRESH_BINARY);
|
||||
|
||||
preMask.convertTo(preMaskFloat, CV_32F);
|
||||
GaussianBlur(preMaskFloat, preMaskFloat, Size(gaussFiltSize, gaussFiltSize), 0, 0);
|
||||
// Change threshold.
|
||||
preMaskFloat *= (0.5/0.95);
|
||||
// Rounding conversion.
|
||||
preMaskFloat.convertTo(preMask, CV_8U);
|
||||
|
||||
// If there's no template mask, we can apply image masks to gradients only once.
|
||||
// Otherwise, we'll need to combine the template and image masks at each iteration.
|
||||
if (templateMask.empty())
|
||||
{
|
||||
cv::Mat zeroMask = (preMask == 0);
|
||||
gradientX.setTo(0, zeroMask);
|
||||
gradientY.setTo(0, zeroMask);
|
||||
}
|
||||
}
|
||||
|
||||
// matrices needed for solving linear equation system for maximizing ECC
|
||||
Mat jacobian = Mat(hs, ws * numberOfParameters, type);
|
||||
@@ -505,6 +531,15 @@ double cv::findTransformECC(InputArray templateImage, InputArray inputImage, Inp
|
||||
warpPerspective(preMask, imageMask, map, imageMask.size(), maskFlags);
|
||||
}
|
||||
|
||||
if (!templateMask.empty())
|
||||
{
|
||||
cv::bitwise_and(imageMask, templtMask, imageMask);
|
||||
|
||||
cv::Mat zeroMask = (imageMask == 0);
|
||||
gradientXWarped.setTo(0, zeroMask);
|
||||
gradientYWarped.setTo(0, zeroMask);
|
||||
}
|
||||
|
||||
Scalar imgMean, imgStd, tmpMean, tmpStd;
|
||||
meanStdDev(imageWarped, imgMean, imgStd, imageMask);
|
||||
meanStdDev(templateFloat, tmpMean, tmpStd, imageMask);
|
||||
@@ -576,6 +611,18 @@ double cv::findTransformECC(InputArray templateImage, InputArray inputImage, Inp
|
||||
return rho;
|
||||
}
|
||||
|
||||
double cv::findTransformECC(InputArray templateImage,
|
||||
InputArray inputImage,
|
||||
InputOutputArray warpMatrix,
|
||||
int motionType,
|
||||
TermCriteria criteria,
|
||||
InputArray inputMask,
|
||||
int gaussFiltSize
|
||||
) {
|
||||
return findTransformECCWithMask(templateImage, inputImage, noArray(), inputMask,
|
||||
warpMatrix, motionType, criteria, gaussFiltSize);
|
||||
}
|
||||
|
||||
double cv::findTransformECC(InputArray templateImage, InputArray inputImage, InputOutputArray warpMatrix,
|
||||
int motionType, TermCriteria criteria, InputArray inputMask) {
|
||||
// Use default value of 5 for gaussFiltSize to maintain backward compatibility.
|
||||
|
||||
@@ -342,6 +342,26 @@ bool CV_ECC_Test_Mask::test(const Mat testImg) {
|
||||
// Test with non-default gaussian blur.
|
||||
findTransformECC(warpedImage, testImg, mapTranslation, 0, criteria, mask, 1);
|
||||
|
||||
if (!checkMap(mapTranslation, translationGround))
|
||||
return false;
|
||||
|
||||
// Test with template mask.
|
||||
Mat_<unsigned char> warpedMask = Mat_<unsigned char>::ones(warpedImage.rows, warpedImage.cols);
|
||||
for (int i=warpedImage.rows*1/3; i<warpedImage.rows*2/3; i++) {
|
||||
for (int j=warpedImage.cols*1/3; j<warpedImage.cols*2/3; j++) {
|
||||
warpedMask(i, j) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
findTransformECCWithMask(warpedImage, testImg, warpedMask, mask, mapTranslation, 0,
|
||||
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
|
||||
|
||||
if (!checkMap(mapTranslation, translationGround))
|
||||
return false;
|
||||
|
||||
// Test with non-default gaussian blur.
|
||||
findTransformECCWithMask(warpedImage, testImg, warpedMask, mask, mapTranslation, 0, criteria, 1);
|
||||
|
||||
if (!checkMap(mapTranslation, translationGround))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -9,12 +9,10 @@ endif()
|
||||
if(NOT HAVE_ARAVIS_API)
|
||||
find_path(ARAVIS_INCLUDE "arv.h"
|
||||
PATHS "${ARAVIS_ROOT}" ENV ARAVIS_ROOT
|
||||
PATH_SUFFIXES "include/aravis-0.8"
|
||||
NO_DEFAULT_PATH)
|
||||
PATH_SUFFIXES "include/aravis-0.8")
|
||||
find_library(ARAVIS_LIBRARY "aravis-0.8"
|
||||
PATHS "${ARAVIS_ROOT}" ENV ARAVIS_ROOT
|
||||
PATH_SUFFIXES "lib"
|
||||
NO_DEFAULT_PATH)
|
||||
PATH_SUFFIXES "lib")
|
||||
if(ARAVIS_INCLUDE AND ARAVIS_LIBRARY)
|
||||
set(HAVE_ARAVIS_API TRUE)
|
||||
file(STRINGS "${ARAVIS_INCLUDE}/arvversion.h" ver_strings REGEX "#define +ARAVIS_(MAJOR|MINOR|MICRO)_VERSION.*")
|
||||
|
||||
@@ -127,6 +127,8 @@ protected:
|
||||
|
||||
void autoExposureControl(const Mat &);
|
||||
|
||||
double getExpectedMidGrey(ArvPixelFormat fmt) const;
|
||||
|
||||
ArvCamera *camera; // Camera to control.
|
||||
ArvStream *stream; // Object for video stream reception.
|
||||
void *framebuffer; //
|
||||
@@ -269,6 +271,19 @@ bool CvCaptureCAM_Aravis::open( int index )
|
||||
|
||||
// get initial values
|
||||
pixelFormat = arv_camera_get_pixel_format(camera, NULL);
|
||||
|
||||
// If camera's pixel format is not one of the supported formats, set a default
|
||||
if (pixelFormat != ARV_PIXEL_FORMAT_MONO_8 &&
|
||||
pixelFormat != ARV_PIXEL_FORMAT_BAYER_GR_8 &&
|
||||
pixelFormat != ARV_PIXEL_FORMAT_MONO_12 &&
|
||||
pixelFormat != ARV_PIXEL_FORMAT_MONO_16) {
|
||||
pixelFormat = ARV_PIXEL_FORMAT_MONO_8;
|
||||
arv_camera_set_pixel_format(camera, pixelFormat, NULL);
|
||||
CV_LOG_WARNING(NULL, "Current camera pixel format is not supported. Failed back to MONO_8.");
|
||||
}
|
||||
|
||||
midGrey = getExpectedMidGrey(pixelFormat);
|
||||
|
||||
exposure = exposureAvailable ? arv_camera_get_exposure_time(camera, NULL) : 0;
|
||||
gain = gainAvailable ? arv_camera_get_gain(camera, NULL) : 0;
|
||||
fps = arv_camera_get_frame_rate(camera, NULL);
|
||||
@@ -489,6 +504,26 @@ double CvCaptureCAM_Aravis::getProperty( int property_id ) const
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
double CvCaptureCAM_Aravis::getExpectedMidGrey(ArvPixelFormat fmt) const
|
||||
{
|
||||
double grey = 0.;
|
||||
switch(fmt)
|
||||
{
|
||||
case ARV_PIXEL_FORMAT_MONO_8:
|
||||
case ARV_PIXEL_FORMAT_BAYER_GR_8:
|
||||
grey = 128.;
|
||||
break;
|
||||
case ARV_PIXEL_FORMAT_MONO_12:
|
||||
grey = 2048.;
|
||||
break;
|
||||
case ARV_PIXEL_FORMAT_MONO_16:
|
||||
grey = 32768.;
|
||||
break;
|
||||
}
|
||||
|
||||
return grey;
|
||||
}
|
||||
|
||||
bool CvCaptureCAM_Aravis::setProperty( int property_id, double value )
|
||||
{
|
||||
switch(property_id) {
|
||||
@@ -535,24 +570,22 @@ bool CvCaptureCAM_Aravis::setProperty( int property_id, double value )
|
||||
case MODE_GREY:
|
||||
case MODE_Y800:
|
||||
newFormat = ARV_PIXEL_FORMAT_MONO_8;
|
||||
targetGrey = 128;
|
||||
break;
|
||||
case MODE_Y12:
|
||||
newFormat = ARV_PIXEL_FORMAT_MONO_12;
|
||||
targetGrey = 2048;
|
||||
break;
|
||||
case MODE_Y16:
|
||||
newFormat = ARV_PIXEL_FORMAT_MONO_16;
|
||||
targetGrey = 32768;
|
||||
break;
|
||||
case MODE_GRBG:
|
||||
newFormat = ARV_PIXEL_FORMAT_BAYER_GR_8;
|
||||
targetGrey = 128;
|
||||
break;
|
||||
}
|
||||
|
||||
if(newFormat != pixelFormat) {
|
||||
stopCapture();
|
||||
arv_camera_set_pixel_format(camera, pixelFormat = newFormat, NULL);
|
||||
midGrey = getExpectedMidGrey(newFormat);
|
||||
startCapture();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
|
||||
protected:
|
||||
// Known widget names
|
||||
static const char * PROP_EXPOSURE_COMPENSACTION;
|
||||
static const char * PROP_EXPOSURE_COMPENSATION;
|
||||
static const char * PROP_SELF_TIMER_DELAY;
|
||||
static const char * PROP_MANUALFOCUS;
|
||||
static const char * PROP_AUTOFOCUS;
|
||||
@@ -294,7 +294,7 @@ const char * DigitalCameraCapture::lineDelimiter = "\n";
|
||||
* Those are actually substrings of widget name.
|
||||
* ie. for VIEWFINDER, Nikon uses "viewfinder", while Canon can use "eosviewfinder".
|
||||
*/
|
||||
const char * DigitalCameraCapture::PROP_EXPOSURE_COMPENSACTION =
|
||||
const char * DigitalCameraCapture::PROP_EXPOSURE_COMPENSATION =
|
||||
"exposurecompensation";
|
||||
const char * DigitalCameraCapture::PROP_SELF_TIMER_DELAY = "selftimerdelay";
|
||||
const char * DigitalCameraCapture::PROP_MANUALFOCUS = "manualfocusdrive";
|
||||
@@ -555,7 +555,7 @@ CameraWidget * DigitalCameraCapture::getGenericProperty(int propertyId,
|
||||
return NULL;
|
||||
}
|
||||
case CAP_PROP_EXPOSURE:
|
||||
return findWidgetByName(PROP_EXPOSURE_COMPENSACTION);
|
||||
return findWidgetByName(PROP_EXPOSURE_COMPENSATION);
|
||||
case CAP_PROP_TRIGGER_DELAY:
|
||||
return findWidgetByName(PROP_SELF_TIMER_DELAY);
|
||||
case CAP_PROP_ZOOM:
|
||||
@@ -692,7 +692,7 @@ CameraWidget * DigitalCameraCapture::setGenericProperty(int propertyId,
|
||||
output = false;
|
||||
return NULL;
|
||||
case CAP_PROP_EXPOSURE:
|
||||
return findWidgetByName(PROP_EXPOSURE_COMPENSACTION);
|
||||
return findWidgetByName(PROP_EXPOSURE_COMPENSATION);
|
||||
case CAP_PROP_TRIGGER_DELAY:
|
||||
return findWidgetByName(PROP_SELF_TIMER_DELAY);
|
||||
case CAP_PROP_ZOOM:
|
||||
|
||||
@@ -448,50 +448,68 @@ public:
|
||||
|
||||
STDMETHODIMP OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample *pSample) CV_OVERRIDE
|
||||
{
|
||||
HRESULT hr = 0;
|
||||
cv::AutoLock lock(m_mutex);
|
||||
|
||||
if (SUCCEEDED(hrStatus))
|
||||
HRESULT hr = S_OK;
|
||||
try
|
||||
{
|
||||
if (pSample)
|
||||
cv::AutoLock lock(m_mutex);
|
||||
|
||||
if (SUCCEEDED(hrStatus))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): got frame at " << llTimestamp);
|
||||
if (m_capturedFrames.size() >= MSMF_READER_MAX_QUEUE_SIZE)
|
||||
if (pSample)
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): got frame at " << llTimestamp);
|
||||
if (m_capturedFrames.size() >= MSMF_READER_MAX_QUEUE_SIZE)
|
||||
{
|
||||
#if 0
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop frame (not processed). Timestamp=" << m_capturedFrames.front().timestamp);
|
||||
m_capturedFrames.pop();
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop frame (not processed). Timestamp=" << m_capturedFrames.front().timestamp);
|
||||
m_capturedFrames.pop();
|
||||
#else
|
||||
// this branch reduces latency if we drop frames due to slow processing.
|
||||
// avoid fetching of already outdated frames from the queue's front.
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop previous frames (not processed): " << m_capturedFrames.size());
|
||||
std::queue<CapturedFrameInfo>().swap(m_capturedFrames); // similar to missing m_capturedFrames.clean();
|
||||
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop previous frames (not processed): " << m_capturedFrames.size());
|
||||
std::queue<CapturedFrameInfo>().swap(m_capturedFrames); // similar to missing m_capturedFrames.clean();
|
||||
#endif
|
||||
}
|
||||
m_capturedFrames.emplace(CapturedFrameInfo{ llTimestamp, _ComPtr<IMFSample>(pSample), hrStatus });
|
||||
}
|
||||
m_capturedFrames.emplace(CapturedFrameInfo{ llTimestamp, _ComPtr<IMFSample>(pSample), hrStatus });
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): OnReadSample() is called with error status: " << hrStatus);
|
||||
}
|
||||
if (MF_SOURCE_READERF_ENDOFSTREAM & dwStreamFlags)
|
||||
{
|
||||
// Reached the end of the stream.
|
||||
m_bEOS = true;
|
||||
}
|
||||
m_hrStatus = hrStatus;
|
||||
|
||||
if (FAILED(hr = m_reader->ReadSample(dwStreamIndex, 0, NULL, NULL, NULL, NULL)))
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): async ReadSample() call is failed with error status: " << hr);
|
||||
m_bEOS = true;
|
||||
}
|
||||
|
||||
if (pSample || m_bEOS)
|
||||
{
|
||||
SetEvent(m_hEvent);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (const _com_error& e)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): OnReadSample() is called with error status: " << hrStatus);
|
||||
std::string msg;
|
||||
#ifdef _UNICODE
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> conv;
|
||||
msg = conv.to_bytes(e.ErrorMessage());
|
||||
#else
|
||||
msg = std::string(e.ErrorMessage());
|
||||
#endif
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): _com_error in OnReadSample: " << msg);
|
||||
return S_OK; // Keep callback alive
|
||||
}
|
||||
|
||||
if (MF_SOURCE_READERF_ENDOFSTREAM & dwStreamFlags)
|
||||
catch (...)
|
||||
{
|
||||
// Reached the end of the stream.
|
||||
m_bEOS = true;
|
||||
}
|
||||
m_hrStatus = hrStatus;
|
||||
|
||||
if (FAILED(hr = m_reader->ReadSample(dwStreamIndex, 0, NULL, NULL, NULL, NULL)))
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): async ReadSample() call is failed with error status: " << hr);
|
||||
m_bEOS = true;
|
||||
}
|
||||
|
||||
if (pSample || m_bEOS)
|
||||
{
|
||||
SetEvent(m_hEvent);
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): Unknown exception in OnReadSample");
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1758,82 +1776,108 @@ bool CvCapture_MSMF::grabFrame()
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
if (grabIsDone)
|
||||
try
|
||||
{
|
||||
grabIsDone = false;
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): return pre-grabbed frame " << usedVideoSampleTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
audioFrame = Mat();
|
||||
if (readCallback) // async "live" capture mode
|
||||
{
|
||||
audioSamples.push_back(NULL);
|
||||
HRESULT hr = 0;
|
||||
SourceReaderCB* reader = ((SourceReaderCB*)readCallback.Get());
|
||||
DWORD dwStreamIndex = 0;
|
||||
if (videoStream != -1)
|
||||
dwStreamIndex = dwVideoStreamIndex;
|
||||
if (audioStream != -1)
|
||||
dwStreamIndex = dwAudioStreamIndex;
|
||||
if (!reader->m_reader)
|
||||
if (grabIsDone)
|
||||
{
|
||||
// Initiate capturing with async callback
|
||||
reader->m_reader = videoFileSource.Get();
|
||||
reader->m_dwStreamIndex = dwStreamIndex;
|
||||
if (FAILED(hr = videoFileSource->ReadSample(dwStreamIndex, 0, NULL, NULL, NULL, NULL)))
|
||||
grabIsDone = false;
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): return pre-grabbed frame " << usedVideoSampleTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
audioFrame = Mat();
|
||||
if (readCallback) // async "live" capture mode
|
||||
{
|
||||
audioSamples.push_back(NULL);
|
||||
HRESULT hr = 0;
|
||||
SourceReaderCB* reader = ((SourceReaderCB*)readCallback.Get());
|
||||
DWORD dwStreamIndex = 0;
|
||||
if (videoStream != -1)
|
||||
dwStreamIndex = dwVideoStreamIndex;
|
||||
if (audioStream != -1)
|
||||
dwStreamIndex = dwAudioStreamIndex;
|
||||
if (!reader->m_reader)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "videoio(MSMF): can't grab frame - initial async ReadSample() call failed: " << hr);
|
||||
reader->m_reader = NULL;
|
||||
// Initiate capturing with async callback
|
||||
reader->m_reader = videoFileSource.Get();
|
||||
reader->m_dwStreamIndex = dwStreamIndex;
|
||||
if (FAILED(hr = videoFileSource->ReadSample(dwStreamIndex, 0, NULL, NULL, NULL, NULL)))
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "videoio(MSMF): can't grab frame - initial async ReadSample() call failed: " << hr);
|
||||
reader->m_reader = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
BOOL bEOS = false;
|
||||
LONGLONG timestamp = 0;
|
||||
if (FAILED(hr = reader->Wait( videoStream == -1 ? INFINITE : 10000, (videoStream != -1) ? usedVideoSample : audioSamples[0], timestamp, bEOS))) // 10 sec
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): can't grab frame. Error: " << hr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
BOOL bEOS = false;
|
||||
LONGLONG timestamp = 0;
|
||||
if (FAILED(hr = reader->Wait( videoStream == -1 ? INFINITE : 10000, (videoStream != -1) ? usedVideoSample : audioSamples[0], timestamp, bEOS))) // 10 sec
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): can't grab frame. Error: " << hr);
|
||||
return false;
|
||||
}
|
||||
if (bEOS)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): EOS signal. Capture stream is lost");
|
||||
return false;
|
||||
}
|
||||
if (videoStream != -1)
|
||||
usedVideoSampleTime = timestamp;
|
||||
if (audioStream != -1)
|
||||
return configureAudioFrame();
|
||||
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): grabbed frame " << usedVideoSampleTime);
|
||||
return true;
|
||||
}
|
||||
else if (isOpen)
|
||||
{
|
||||
if (vEOS)
|
||||
return false;
|
||||
|
||||
bool returnFlag = true;
|
||||
|
||||
if (videoStream != -1)
|
||||
{
|
||||
if (!vEOS)
|
||||
returnFlag &= grabVideoFrame();
|
||||
if (!returnFlag)
|
||||
if (bEOS)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): EOS signal. Capture stream is lost");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (videoStream != -1)
|
||||
usedVideoSampleTime = timestamp;
|
||||
if (audioStream != -1)
|
||||
return configureAudioFrame();
|
||||
|
||||
if (audioStream != -1)
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): grabbed frame " << usedVideoSampleTime);
|
||||
return true;
|
||||
}
|
||||
else if (isOpen)
|
||||
{
|
||||
const int bytesPerSample = (captureAudioFormat.bit_per_sample/8) * captureAudioFormat.nChannels;
|
||||
bufferedAudioDuration = (double)(bufferAudioData.size()/bytesPerSample)/captureAudioFormat.nSamplesPerSec;
|
||||
audioFrame.release();
|
||||
if (!aEOS)
|
||||
returnFlag &= grabAudioFrame();
|
||||
}
|
||||
if (vEOS)
|
||||
return false;
|
||||
|
||||
return returnFlag;
|
||||
bool returnFlag = true;
|
||||
|
||||
if (videoStream != -1)
|
||||
{
|
||||
if (!vEOS)
|
||||
returnFlag &= grabVideoFrame();
|
||||
if (!returnFlag)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (audioStream != -1)
|
||||
{
|
||||
const int bytesPerSample = (captureAudioFormat.bit_per_sample/8) * captureAudioFormat.nChannels;
|
||||
bufferedAudioDuration = (double)(bufferAudioData.size()/bytesPerSample)/captureAudioFormat.nSamplesPerSec;
|
||||
audioFrame.release();
|
||||
if (!aEOS)
|
||||
returnFlag &= grabAudioFrame();
|
||||
}
|
||||
|
||||
return returnFlag;
|
||||
}
|
||||
}
|
||||
catch (const _com_error& e)
|
||||
{
|
||||
std::string msg;
|
||||
#ifdef _UNICODE
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> conv;
|
||||
msg = conv.to_bytes(e.ErrorMessage());
|
||||
#else
|
||||
msg = std::string(e.ErrorMessage());
|
||||
#endif
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): _com_error caught in grabFrame: " << msg);
|
||||
return false;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): std::exception caught in grabFrame: " << e.what());
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): Unknown exception caught in grabFrame");
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user