Skip to content

Commit 691c3d1

Browse files
committed
Merge pull request opencv#18673 from dmatveev:dm/upstream_desync
2 parents 56d2b71 + ca8bb8d commit 691c3d1

40 files changed

+2827
-195
lines changed

modules/gapi/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ set(gapi_srcs
7474
src/api/kernels_imgproc.cpp
7575
src/api/kernels_video.cpp
7676
src/api/kernels_nnparsers.cpp
77+
src/api/kernels_streaming.cpp
7778
src/api/render.cpp
7879
src/api/render_ocv.cpp
7980
src/api/ginfer.cpp
@@ -97,6 +98,7 @@ set(gapi_srcs
9798
src/compiler/passes/pattern_matching.cpp
9899
src/compiler/passes/perform_substitution.cpp
99100
src/compiler/passes/streaming.cpp
101+
src/compiler/passes/intrin.cpp
100102

101103
# Executor
102104
src/executor/gexecutor.cpp

modules/gapi/include/opencv2/gapi.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,8 @@
3333
#include <opencv2/gapi/gkernel.hpp>
3434
#include <opencv2/gapi/operators.hpp>
3535

36+
// Include this file here to avoid cyclic dependency between
37+
// Desync & GKernel & GComputation & GStreamingCompiled.
38+
#include <opencv2/gapi/streaming/desync.hpp>
39+
3640
#endif // OPENCV_GAPI_HPP

modules/gapi/include/opencv2/gapi/garray.hpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,14 @@ namespace detail
284284
return static_cast<VectorRefT<T>&>(*m_ref).rref();
285285
}
286286

287+
// Check if was created for/from std::vector<T>
288+
template <typename T> bool holds() const
289+
{
290+
if (!m_ref) return false;
291+
using U = typename std::decay<T>::type;
292+
return dynamic_cast<VectorRefT<U>*>(m_ref.get()) != nullptr;
293+
}
294+
287295
void mov(VectorRef &v)
288296
{
289297
m_ref->mov(*v.m_ref);
@@ -341,15 +349,18 @@ template<typename T> class GArray
341349
explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor
342350
: m_ref(ref) { putDetails(); } // (used by GCall, not for users)
343351

344-
detail::GArrayU strip() const { return m_ref; }
345-
346-
private:
347-
static void VCTor(detail::VectorRef& vref) {
352+
/// @private
353+
detail::GArrayU strip() const {
354+
return m_ref;
355+
}
356+
/// @private
357+
static void VCtor(detail::VectorRef& vref) {
348358
vref.reset<HT>();
349-
vref.storeKind<HT>();
350359
}
360+
361+
private:
351362
void putDetails() {
352-
m_ref.setConstructFcn(&VCTor);
363+
m_ref.setConstructFcn(&VCtor);
353364
m_ref.specifyType<HT>(); // FIXME: to unify those 2 to avoid excessive dynamic_cast
354365
m_ref.storeKind<HT>(); //
355366
}

modules/gapi/include/opencv2/gapi/gkernel.hpp

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ namespace cv {
2828

2929
using GShapes = std::vector<GShape>;
3030
using GKinds = std::vector<cv::detail::OpaqueKind>;
31+
using GCtors = std::vector<detail::HostCtor>;
3132

3233
// GKernel describes kernel API to the system
3334
// FIXME: add attributes of a kernel, (e.g. number and types
@@ -41,6 +42,7 @@ struct GAPI_EXPORTS GKernel
4142
M outMeta; // generic adaptor to API::outMeta(...)
4243
GShapes outShapes; // types (shapes) kernel's outputs
4344
GKinds inKinds; // kinds of kernel's inputs (fixme: below)
45+
GCtors outCtors; // captured constructors for template output types
4446
};
4547
// TODO: It's questionable if inKinds should really be here. Instead,
4648
// this information could come from meta.
@@ -60,30 +62,27 @@ namespace detail
6062
// yield() is used in graph construction time as a generic method to obtain
6163
// lazy "return value" of G-API operations
6264
//
63-
namespace
65+
template<typename T> struct Yield;
66+
template<> struct Yield<cv::GMat>
6467
{
65-
template<typename T> struct Yield;
66-
template<> struct Yield<cv::GMat>
67-
{
68-
static inline cv::GMat yield(cv::GCall &call, int i) { return call.yield(i); }
69-
};
70-
template<> struct Yield<cv::GMatP>
71-
{
72-
static inline cv::GMatP yield(cv::GCall &call, int i) { return call.yieldP(i); }
73-
};
74-
template<> struct Yield<cv::GScalar>
75-
{
76-
static inline cv::GScalar yield(cv::GCall &call, int i) { return call.yieldScalar(i); }
77-
};
78-
template<typename U> struct Yield<cv::GArray<U> >
79-
{
80-
static inline cv::GArray<U> yield(cv::GCall &call, int i) { return call.yieldArray<U>(i); }
81-
};
82-
template<typename U> struct Yield<cv::GOpaque<U> >
83-
{
84-
static inline cv::GOpaque<U> yield(cv::GCall &call, int i) { return call.yieldOpaque<U>(i); }
85-
};
86-
} // anonymous namespace
68+
static inline cv::GMat yield(cv::GCall &call, int i) { return call.yield(i); }
69+
};
70+
template<> struct Yield<cv::GMatP>
71+
{
72+
static inline cv::GMatP yield(cv::GCall &call, int i) { return call.yieldP(i); }
73+
};
74+
template<> struct Yield<cv::GScalar>
75+
{
76+
static inline cv::GScalar yield(cv::GCall &call, int i) { return call.yieldScalar(i); }
77+
};
78+
template<typename U> struct Yield<cv::GArray<U> >
79+
{
80+
static inline cv::GArray<U> yield(cv::GCall &call, int i) { return call.yieldArray<U>(i); }
81+
};
82+
template<typename U> struct Yield<cv::GOpaque<U> >
83+
{
84+
static inline cv::GOpaque<U> yield(cv::GCall &call, int i) { return call.yieldOpaque<U>(i); }
85+
};
8786

8887
////////////////////////////////////////////////////////////////////////////
8988
// Helper classes which brings outputMeta() marshalling to kernel
@@ -215,7 +214,8 @@ class GKernelTypeM<K, std::function<std::tuple<R...>(Args...)> >
215214
, K::tag()
216215
, &K::getOutMeta
217216
, {detail::GTypeTraits<R>::shape...}
218-
, {detail::GTypeTraits<Args>::op_kind...}});
217+
, {detail::GTypeTraits<Args>::op_kind...}
218+
, {detail::GObtainCtor<R>::get()...}});
219219
call.pass(args...); // TODO: std::forward() here?
220220
return yield(call, typename detail::MkSeq<sizeof...(R)>::type());
221221
}
@@ -240,7 +240,8 @@ class GKernelType<K, std::function<R(Args...)> >
240240
, K::tag()
241241
, &K::getOutMeta
242242
, {detail::GTypeTraits<R>::shape}
243-
, {detail::GTypeTraits<Args>::op_kind...}});
243+
, {detail::GTypeTraits<Args>::op_kind...}
244+
, {detail::GObtainCtor<R>::get()}});
244245
call.pass(args...);
245246
return detail::Yield<R>::yield(call, 0);
246247
}
@@ -459,11 +460,6 @@ namespace gapi {
459460
std::vector<GTransform> m_transformations;
460461

461462
protected:
462-
/// @private
463-
// Check if package contains ANY implementation of a kernel API
464-
// by API textual id.
465-
bool includesAPI(const std::string &id) const;
466-
467463
/// @private
468464
// Remove ALL implementations of the given API (identified by ID)
469465
void removeAPI(const std::string &id);
@@ -566,6 +562,9 @@ namespace gapi {
566562
return includesAPI(KAPI::id());
567563
}
568564

565+
/// @private
566+
bool includesAPI(const std::string &id) const;
567+
569568
// FIXME: The below comment is wrong, and who needs this function?
570569
/**
571570
* @brief Find a kernel (by its API)

modules/gapi/include/opencv2/gapi/gopaque.hpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -295,25 +295,27 @@ namespace detail
295295
template<typename T> class GOpaque
296296
{
297297
public:
298-
GOpaque() { putDetails(); } // Empty constructor
299-
explicit GOpaque(detail::GOpaqueU &&ref) // GOpaqueU-based constructor
300-
: m_ref(ref) { putDetails(); } // (used by GCall, not for users)
301-
302-
detail::GOpaqueU strip() const { return m_ref; }
303-
304-
private:
305298
// Host type (or Flat type) - the type this GOpaque is actually
306299
// specified to.
307300
using HT = typename detail::flatten_g<util::decay_t<T>>::type;
308301

309-
static void CTor(detail::OpaqueRef& ref) {
302+
GOpaque() { putDetails(); } // Empty constructor
303+
explicit GOpaque(detail::GOpaqueU &&ref) // GOpaqueU-based constructor
304+
: m_ref(ref) { putDetails(); } // (used by GCall, not for users)
305+
306+
/// @private
307+
detail::GOpaqueU strip() const {
308+
return m_ref;
309+
}
310+
/// @private
311+
static void Ctor(detail::OpaqueRef& ref) {
310312
ref.reset<HT>();
311-
ref.storeKind<HT>();
312313
}
314+
private:
313315
void putDetails() {
314-
m_ref.setConstructFcn(&CTor);
315-
m_ref.specifyType<HT>(); // FIXME: to unify those 2 to avoid excessive dynamic_cast
316-
m_ref.storeKind<HT>(); //
316+
m_ref.setConstructFcn(&Ctor);
317+
m_ref.specifyType<HT>();
318+
m_ref.storeKind<HT>();
317319
}
318320

319321
detail::GOpaqueU m_ref;

modules/gapi/include/opencv2/gapi/gstreaming.hpp

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,99 @@
88
#ifndef OPENCV_GAPI_GSTREAMING_COMPILED_HPP
99
#define OPENCV_GAPI_GSTREAMING_COMPILED_HPP
1010

11+
#include <memory>
1112
#include <vector>
1213

1314
#include <opencv2/gapi/opencv_includes.hpp>
1415
#include <opencv2/gapi/own/assert.hpp>
16+
#include <opencv2/gapi/util/optional.hpp>
1517
#include <opencv2/gapi/garg.hpp>
1618
#include <opencv2/gapi/streaming/source.hpp>
1719

1820
namespace cv {
1921

22+
template<class T> using optional = cv::util::optional<T>;
23+
24+
namespace detail {
25+
template<typename T> struct wref_spec {
26+
using type = T;
27+
};
28+
template<typename T> struct wref_spec<std::vector<T> > {
29+
using type = T;
30+
};
31+
32+
template<typename RefHolder>
33+
struct OptRef {
34+
struct OptHolder {
35+
virtual void mov(RefHolder &h) = 0;
36+
virtual void reset() = 0;
37+
virtual ~OptHolder() = default;
38+
using Ptr = std::shared_ptr<OptHolder>;
39+
};
40+
template<class T> struct Holder final: OptHolder {
41+
std::reference_wrapper<cv::optional<T> > m_opt_ref;
42+
43+
explicit Holder(cv::optional<T>& opt) : m_opt_ref(std::ref(opt)) {
44+
}
45+
virtual void mov(RefHolder &h) override {
46+
using U = typename wref_spec<T>::type;
47+
m_opt_ref.get() = cv::util::make_optional(std::move(h.template wref<U>()));
48+
}
49+
virtual void reset() override {
50+
m_opt_ref.get().reset();
51+
}
52+
};
53+
template<class T>
54+
explicit OptRef(cv::optional<T>& t) : m_opt{new Holder<T>(t)} {}
55+
void mov(RefHolder &h) { m_opt->mov(h); }
56+
void reset() { m_opt->reset();}
57+
private:
58+
typename OptHolder::Ptr m_opt;
59+
};
60+
using OptionalVectorRef = OptRef<cv::detail::VectorRef>;
61+
using OptionalOpaqueRef = OptRef<cv::detail::OpaqueRef>;
62+
} // namespace detail
63+
64+
// TODO: Keep it in sync with GRunArgP (derive the type automatically?)
65+
using GOptRunArgP = util::variant<
66+
optional<cv::Mat>*,
67+
optional<cv::RMat>*,
68+
optional<cv::Scalar>*,
69+
cv::detail::OptionalVectorRef,
70+
cv::detail::OptionalOpaqueRef
71+
>;
72+
using GOptRunArgsP = std::vector<GOptRunArgP>;
73+
74+
namespace detail {
75+
76+
template<typename T> inline GOptRunArgP wrap_opt_arg(optional<T>& arg) {
77+
// By default, T goes to an OpaqueRef. All other types are specialized
78+
return GOptRunArgP{OptionalOpaqueRef(arg)};
79+
}
80+
81+
template<typename T> inline GOptRunArgP wrap_opt_arg(optional<std::vector<T> >& arg) {
82+
return GOptRunArgP{OptionalVectorRef(arg)};
83+
}
84+
85+
template<> inline GOptRunArgP wrap_opt_arg(optional<cv::Mat> &m) {
86+
return GOptRunArgP{&m};
87+
}
88+
89+
template<> inline GOptRunArgP wrap_opt_arg(optional<cv::Scalar> &s) {
90+
return GOptRunArgP{&s};
91+
}
92+
93+
} // namespace detail
94+
95+
// Now cv::gout() may produce an empty vector (see "dynamic graphs"), so
96+
// there may be a conflict between these two. State here that Opt version
97+
// _must_ have at least one input for this overload
98+
template<typename T, typename... Ts>
99+
inline GOptRunArgsP gout(optional<T>&arg, optional<Ts>&... args)
100+
{
101+
return GOptRunArgsP{ detail::wrap_opt_arg(arg), detail::wrap_opt_arg(args)... };
102+
}
103+
20104
/**
21105
* \addtogroup gapi_main_classes
22106
* @{
@@ -169,6 +253,44 @@ class GAPI_EXPORTS_W_SIMPLE GStreamingCompiled
169253
// NB: Used from python
170254
GAPI_WRAP std::tuple<bool, cv::GRunArgs> pull();
171255

256+
/**
257+
* @brief Get some next available data from the pipeline.
258+
*
259+
* This method takes a vector of cv::optional object. An object is
260+
* assigned to some value if this value is available (ready) at
261+
* the time of the call, and resets the object to empty() if it is
262+
* not.
263+
*
264+
* This is a blocking method which guarantees that some data has
265+
* been written to the output vector on return.
266+
*
267+
* Using this method only makes sense if the graph has
268+
* desynchronized parts (see cv::gapi::desync). If there is no
269+
* desynchronized parts in the graph, the behavior of this
270+
* method is identical to the regular pull() (all data objects are
271+
* produced synchronously in the output vector).
272+
*
273+
* Use gout() to create an output parameter vector.
274+
*
275+
* Output vectors must have the same number of elements as defined
276+
* in the cv::GComputation protocol (at the moment of its
277+
* construction). Shapes of elements also must conform to protocol
278+
* (e.g. cv::optional<cv::Mat> needs to be passed where cv::GMat
279+
* has been declared as output, and so on). Run-time exception is
280+
* generated on type mismatch.
281+
*
282+
* This method writes new data into objects passed via output
283+
* vector. If there is no data ready yet, this method blocks. Use
284+
* try_pull() if you need a non-blocking version.
285+
*
286+
* @param outs vector of output parameters to obtain.
287+
* @return true if next result has been obtained,
288+
* false marks end of the stream.
289+
*
290+
* @sa cv::gapi::desync
291+
*/
292+
bool pull(cv::GOptRunArgsP &&outs);
293+
172294
/**
173295
* @brief Try to get the next processed frame from the pipeline.
174296
*

modules/gapi/include/opencv2/gapi/gtype_traits.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,29 @@ namespace detail
191191

192192
template<typename T> using wrap_gapi_helper = WrapValue<typename std::decay<T>::type>;
193193
template<typename T> using wrap_host_helper = WrapValue<typename std::decay<g_type_of_t<T> >::type>;
194+
195+
// Union type for various user-defined type constructors (GArray<T>,
196+
// GOpaque<T>, etc)
197+
//
198+
// TODO: Replace construct-only API with a more generic one (probably
199+
// with bits of introspection)
200+
//
201+
// Not required for non-user-defined types (GMat, GScalar, etc)
202+
using HostCtor = util::variant
203+
< util::monostate
204+
, detail::ConstructVec
205+
, detail::ConstructOpaque
206+
>;
207+
208+
template<typename T> struct GObtainCtor {
209+
static HostCtor get() { return HostCtor{}; }
210+
};
211+
template<typename T> struct GObtainCtor<GArray<T> > {
212+
static HostCtor get() { return HostCtor{ConstructVec{&GArray<T>::VCtor}}; };
213+
};
214+
template<typename T> struct GObtainCtor<GOpaque<T> > {
215+
static HostCtor get() { return HostCtor{ConstructOpaque{&GOpaque<T>::Ctor}}; };
216+
};
194217
} // namespace detail
195218
} // namespace cv
196219

0 commit comments

Comments
 (0)