mirror of
https://github.com/opencv/opencv.git
synced 2024-12-14 17:29:17 +08:00
2477103707
* G-API-NG/Streaming: Introduced a Streaming API Now a GComputation can be compiled in a special "streaming" way and then "played" on a video stream. Currently only VideoCapture is supported as an input source. * G-API-NG/Streaming: added threading & real streaming * G-API-NG/Streaming: Added tests & docs on Copy kernel - Added very simple pipeline tests, not all data types are covered yet (in fact, only GMat is tested now); - Started testing non-OCV backends in the streaming mode; - Added required fixes to Fluid backend, likely it works OK now; - Added required fixes to OCL backend, and now it is likely broken - Also added a UMat-based (OCL) version of Copy kernel * G-API-NG/Streaming: Added own concurrent queue class - Used only if TBB is not available * G-API-NG/Streaming: Fixing various issues - Added missing header to CMakeLists.txt - Fixed various CI issues and warnings * G-API-NG/Streaming: Fixed a compile-time GScalar queue deadlock - GStreamingExecutor blindly created island's input queues for compile-time (value-initialized) GScalars which didn't have any producers, making island actor threads wait there forever * G-API-NG/Streaming: Dropped own version of Copy kernel One was added into master already * G-API-NG/Streaming: Addressed GArray<T> review comments - Added tests on mov() - Removed unnecessary changes in garray.hpp * G-API-NG/Streaming: Added Doxygen comments to new public APIs Also fixed some other comments in the code * G-API-NG/Streaming: Removed debug info, added some comments & renamed vars * G-API-NG/Streaming: Fixed own-vs-cv abstraction leak - Now every island is triggered with own:: (instead of cv::) data objects as inputs; - Changes in Fluid backend required to support cv::Mat/Scalar were reverted; * G-API-NG/Streaming: use holds_alternative<> instead of index/index_of test - Also fixed regression test comments - Also added metadata check comments for GStreamingCompiled * G-API-NG/Streaming: Made start()/stop() more robust - Fixed various possible deadlocks - Unified the shutdown code - Added more tests covering different corner cases on start/stop * G-API-NG/Streaming: Finally fixed Windows crashes In fact the problem hasn't been Windows-only. Island thread popped data from queues without preserving the Cmd objects and without taking the ownership over data acquired so when islands started to process the data, this data may be already freed. Linux version worked only by occasion. * G-API-NG/Streaming: Fixed (I hope so) Windows warnings * G-API-NG/Streaming: fixed typos in internal comments - Also added some more explanation on Streaming/OpenCL status * G-API-NG/Streaming: Added more unit tests on streaming - Various start()/stop()/setSource() call flow combinations * G-API-NG/Streaming: Added tests on own concurrent bounded queue * G-API-NG/Streaming: Added more tests on various data types, + more - Vector/Scalar passed as input; - Vector/Scalar passed in-between islands; - Some more assertions; - Also fixed a deadlock problem when inputs are mixed (1 constant, 1 stream) * G-API-NG/Streaming: Added tests on output data types handling - Vector - Scalar * G-API-NG/Streaming: Fixed test issues with IE + Windows warnings * G-API-NG/Streaming: Decoupled G-API from videoio - Now the core G-API doesn't use a cv::VideoCapture directly, it comes in via an abstract interface; - Polished a little bit the setSource()/start()/stop() semantics, now setSource() is mandatory before ANY call to start(). * G-API-NG/Streaming: Fix STANDALONE build (errors brought by render)
320 lines
11 KiB
C++
320 lines
11 KiB
C++
// This file is part of OpenCV project.
|
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
|
// of this distribution and at http://opencv.org/license.html.
|
|
//
|
|
// Copyright (C) 2018 Intel Corporation
|
|
|
|
|
|
#ifndef OPENCV_GAPI_GARRAY_HPP
|
|
#define OPENCV_GAPI_GARRAY_HPP
|
|
|
|
#include <functional>
|
|
#include <ostream>
|
|
#include <vector>
|
|
#include <memory>
|
|
|
|
#include <opencv2/gapi/own/exports.hpp>
|
|
#include <opencv2/gapi/opencv_includes.hpp>
|
|
|
|
#include <opencv2/gapi/util/variant.hpp>
|
|
#include <opencv2/gapi/util/throw.hpp>
|
|
#include <opencv2/gapi/own/assert.hpp>
|
|
|
|
#include <opencv2/gapi/gmat.hpp> // flatten_g only!
|
|
#include <opencv2/gapi/gscalar.hpp> // flatten_g only!
|
|
|
|
namespace cv
|
|
{
|
|
// Forward declaration; GNode and GOrigin are an internal
|
|
// (user-inaccessible) classes.
|
|
class GNode;
|
|
struct GOrigin;
|
|
|
|
template<typename T> class GArray;
|
|
|
|
/**
|
|
* \addtogroup gapi_meta_args
|
|
* @{
|
|
*/
|
|
struct GArrayDesc
|
|
{
|
|
// FIXME: Body
|
|
// FIXME: Also implement proper operator== then
|
|
bool operator== (const GArrayDesc&) const { return true; }
|
|
};
|
|
template<typename U> GArrayDesc descr_of(const std::vector<U> &) { return {};}
|
|
static inline GArrayDesc empty_array_desc() {return {}; }
|
|
/** @} */
|
|
|
|
std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &desc);
|
|
|
|
namespace detail
|
|
{
|
|
// ConstructVec is a callback which stores information about T and is used by
|
|
// G-API runtime to construct arrays in host memory (T remains opaque for G-API).
|
|
// ConstructVec is carried into G-API internals by GArrayU.
|
|
// Currently it is suitable for Host (CPU) plugins only, real offload may require
|
|
// more information for manual memory allocation on-device.
|
|
class VectorRef;
|
|
using ConstructVec = std::function<void(VectorRef&)>;
|
|
|
|
// This is the base struct for GArrayU type holder
|
|
struct TypeHintBase{virtual ~TypeHintBase() = default;};
|
|
|
|
// This class holds type of initial GArray to be checked from GArrayU
|
|
template <typename T>
|
|
struct TypeHint final : public TypeHintBase{};
|
|
|
|
// This class strips type information from GArray<T> and makes it usable
|
|
// in the G-API graph compiler (expression unrolling, graph generation, etc).
|
|
// Part of GProtoArg.
|
|
class GAPI_EXPORTS GArrayU
|
|
{
|
|
public:
|
|
GArrayU(const GNode &n, std::size_t out); // Operation result constructor
|
|
|
|
template <typename T>
|
|
bool holds() const; // Check if was created from GArray<T>
|
|
|
|
GOrigin& priv(); // Internal use only
|
|
const GOrigin& priv() const; // Internal use only
|
|
|
|
protected:
|
|
GArrayU(); // Default constructor
|
|
template<class> friend class cv::GArray; // (available to GArray<T> only)
|
|
|
|
void setConstructFcn(ConstructVec &&cv); // Store T-aware constructor
|
|
|
|
template <typename T>
|
|
void specifyType(); // Store type of initial GArray<T>
|
|
|
|
std::shared_ptr<GOrigin> m_priv;
|
|
std::shared_ptr<TypeHintBase> m_hint;
|
|
};
|
|
|
|
template <typename T>
|
|
bool GArrayU::holds() const{
|
|
GAPI_Assert(m_hint != nullptr);
|
|
using U = typename std::decay<T>::type;
|
|
return dynamic_cast<TypeHint<U>*>(m_hint.get()) != nullptr;
|
|
};
|
|
|
|
template <typename T>
|
|
void GArrayU::specifyType(){
|
|
m_hint.reset(new TypeHint<typename std::decay<T>::type>);
|
|
};
|
|
|
|
// This class represents a typed STL vector reference.
|
|
// Depending on origins, this reference may be either "just a" reference to
|
|
// an object created externally, OR actually own the underlying object
|
|
// (be value holder).
|
|
class BasicVectorRef
|
|
{
|
|
public:
|
|
std::size_t m_elemSize = 0ul;
|
|
cv::GArrayDesc m_desc;
|
|
virtual ~BasicVectorRef() {}
|
|
|
|
virtual void mov(BasicVectorRef &ref) = 0;
|
|
};
|
|
|
|
template<typename T> class VectorRefT final: public BasicVectorRef
|
|
{
|
|
using empty_t = util::monostate;
|
|
using ro_ext_t = const std::vector<T> *;
|
|
using rw_ext_t = std::vector<T> *;
|
|
using rw_own_t = std::vector<T> ;
|
|
util::variant<empty_t, ro_ext_t, rw_ext_t, rw_own_t> m_ref;
|
|
|
|
inline bool isEmpty() const { return util::holds_alternative<empty_t>(m_ref); }
|
|
inline bool isROExt() const { return util::holds_alternative<ro_ext_t>(m_ref); }
|
|
inline bool isRWExt() const { return util::holds_alternative<rw_ext_t>(m_ref); }
|
|
inline bool isRWOwn() const { return util::holds_alternative<rw_own_t>(m_ref); }
|
|
|
|
void init(const std::vector<T>* vec = nullptr)
|
|
{
|
|
m_elemSize = sizeof(T);
|
|
if (vec) m_desc = cv::descr_of(*vec);
|
|
}
|
|
|
|
public:
|
|
VectorRefT() { init(); }
|
|
virtual ~VectorRefT() {}
|
|
|
|
explicit VectorRefT(const std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
|
|
explicit VectorRefT(std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
|
|
explicit VectorRefT(std::vector<T>&& vec) : m_ref(std::move(vec)) { init(&vec); }
|
|
|
|
// Reset a VectorRefT. Called only for objects instantiated
|
|
// internally in G-API (e.g. temporary GArray<T>'s within a
|
|
// computation). Reset here means both initialization
|
|
// (creating an object) and reset (discarding its existing
|
|
// content before the next execution). Must never be called
|
|
// for external VectorRefTs.
|
|
void reset()
|
|
{
|
|
if (isEmpty())
|
|
{
|
|
std::vector<T> empty_vector;
|
|
m_desc = cv::descr_of(empty_vector);
|
|
m_ref = std::move(empty_vector);
|
|
GAPI_Assert(isRWOwn());
|
|
}
|
|
else if (isRWOwn())
|
|
{
|
|
util::get<rw_own_t>(m_ref).clear();
|
|
}
|
|
else GAPI_Assert(false); // shouldn't be called in *EXT modes
|
|
}
|
|
|
|
// Obtain a WRITE reference to underlying object
|
|
// Used by CPU kernel API wrappers when a kernel execution frame
|
|
// is created
|
|
std::vector<T>& wref()
|
|
{
|
|
GAPI_Assert(isRWExt() || isRWOwn());
|
|
if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
|
|
if (isRWOwn()) return util::get<rw_own_t>(m_ref);
|
|
util::throw_error(std::logic_error("Impossible happened"));
|
|
}
|
|
|
|
// Obtain a READ reference to underlying object
|
|
// Used by CPU kernel API wrappers when a kernel execution frame
|
|
// is created
|
|
const std::vector<T>& rref() const
|
|
{
|
|
// ANY vector can be accessed for reading, even if it declared for
|
|
// output. Example -- a GComputation from [in] to [out1,out2]
|
|
// where [out2] is a result of operation applied to [out1]:
|
|
//
|
|
// GComputation boundary
|
|
// . . . . . . .
|
|
// . .
|
|
// [in] ----> foo() ----> [out1]
|
|
// . . :
|
|
// . . . .:. . .
|
|
// . V .
|
|
// . bar() ---> [out2]
|
|
// . . . . . . . . . . . .
|
|
//
|
|
if (isROExt()) return *util::get<ro_ext_t>(m_ref);
|
|
if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
|
|
if (isRWOwn()) return util::get<rw_own_t>(m_ref);
|
|
util::throw_error(std::logic_error("Impossible happened"));
|
|
}
|
|
|
|
virtual void mov(BasicVectorRef &v) override {
|
|
VectorRefT<T> *tv = dynamic_cast<VectorRefT<T>*>(&v);
|
|
GAPI_Assert(tv != nullptr);
|
|
wref() = std::move(tv->wref());
|
|
}
|
|
};
|
|
|
|
// This class strips type information from VectorRefT<> and makes it usable
|
|
// in the G-API executables (carrying run-time data/information to kernels).
|
|
// Part of GRunArg.
|
|
// Its methods are typed proxies to VectorRefT<T>.
|
|
// VectorRef maintains "reference" semantics so two copies of VectoRef refer
|
|
// to the same underlying object.
|
|
// FIXME: Put a good explanation on why cv::OutputArray doesn't fit this role
|
|
class VectorRef
|
|
{
|
|
std::shared_ptr<BasicVectorRef> m_ref;
|
|
|
|
template<typename T> inline void check() const
|
|
{
|
|
GAPI_DbgAssert(dynamic_cast<VectorRefT<T>*>(m_ref.get()) != nullptr);
|
|
GAPI_Assert(sizeof(T) == m_ref->m_elemSize);
|
|
}
|
|
|
|
public:
|
|
VectorRef() = default;
|
|
template<typename T> explicit VectorRef(const std::vector<T>& vec) : m_ref(new VectorRefT<T>(vec)) {}
|
|
template<typename T> explicit VectorRef(std::vector<T>& vec) : m_ref(new VectorRefT<T>(vec)) {}
|
|
template<typename T> explicit VectorRef(std::vector<T>&& vec) : m_ref(new VectorRefT<T>(vec)) {}
|
|
|
|
template<typename T> void reset()
|
|
{
|
|
if (!m_ref) m_ref.reset(new VectorRefT<T>());
|
|
|
|
check<T>();
|
|
static_cast<VectorRefT<T>&>(*m_ref).reset();
|
|
}
|
|
|
|
template<typename T> std::vector<T>& wref()
|
|
{
|
|
check<T>();
|
|
return static_cast<VectorRefT<T>&>(*m_ref).wref();
|
|
}
|
|
|
|
template<typename T> const std::vector<T>& rref() const
|
|
{
|
|
check<T>();
|
|
return static_cast<VectorRefT<T>&>(*m_ref).rref();
|
|
}
|
|
|
|
void mov(VectorRef &v)
|
|
{
|
|
m_ref->mov(*v.m_ref);
|
|
}
|
|
|
|
cv::GArrayDesc descr_of() const
|
|
{
|
|
return m_ref->m_desc;
|
|
}
|
|
};
|
|
|
|
// Helper (FIXME: work-around?)
|
|
// stripping G types to their host types
|
|
// like cv::GArray<GMat> would still map to std::vector<cv::Mat>
|
|
// but not to std::vector<cv::GMat>
|
|
#if defined(GAPI_STANDALONE)
|
|
# define FLATTEN_NS cv::gapi::own
|
|
#else
|
|
# define FLATTEN_NS cv
|
|
#endif
|
|
template<class T> struct flatten_g;
|
|
template<> struct flatten_g<cv::GMat> { using type = FLATTEN_NS::Mat; };
|
|
template<> struct flatten_g<cv::GScalar> { using type = FLATTEN_NS::Scalar; };
|
|
template<class T> struct flatten_g { using type = T; };
|
|
#undef FLATTEN_NS
|
|
// FIXME: the above mainly duplicates "ProtoToParam" thing from gtyped.hpp
|
|
// but I decided not to include gtyped here - probably worth moving that stuff
|
|
// to some common place? (DM)
|
|
} // namespace detail
|
|
|
|
/** \addtogroup gapi_data_objects
|
|
* @{
|
|
*/
|
|
|
|
template<typename T> class GArray
|
|
{
|
|
public:
|
|
GArray() { putDetails(); } // Empty constructor
|
|
explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor
|
|
: m_ref(ref) { putDetails(); } // (used by GCall, not for users)
|
|
|
|
detail::GArrayU strip() const { return m_ref; }
|
|
|
|
private:
|
|
// Host type (or Flat type) - the type this GArray is actually
|
|
// specified to.
|
|
using HT = typename detail::flatten_g<typename std::decay<T>::type>::type;
|
|
|
|
static void VCTor(detail::VectorRef& vref) {
|
|
vref.reset<HT>();
|
|
}
|
|
void putDetails() {
|
|
m_ref.setConstructFcn(&VCTor);
|
|
m_ref.specifyType<HT>();
|
|
}
|
|
|
|
detail::GArrayU m_ref;
|
|
};
|
|
|
|
/** @} */
|
|
|
|
} // namespace cv
|
|
|
|
#endif // OPENCV_GAPI_GARRAY_HPP
|