Merge pull request #20184 from sivanov-work:fix_gapi_empty_input
[platform/upstream/opencv.git] / modules / gapi / include / opencv2 / gapi / gtype_traits.hpp
1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 //
5 // Copyright (C) 2018-2020 Intel Corporation
6
7
8 #ifndef OPENCV_GAPI_GTYPE_TRAITS_HPP
9 #define OPENCV_GAPI_GTYPE_TRAITS_HPP
10
11 #include <vector>
12 #include <type_traits>
13
14 #include <opencv2/gapi/gmat.hpp>
15 #include <opencv2/gapi/gscalar.hpp>
16 #include <opencv2/gapi/garray.hpp>
17 #include <opencv2/gapi/gopaque.hpp>
18 #include <opencv2/gapi/gframe.hpp>
19 #include <opencv2/gapi/streaming/source.hpp>
20 #include <opencv2/gapi/media.hpp>
21 #include <opencv2/gapi/gcommon.hpp>
22
23 namespace cv
24 {
25 namespace detail
26 {
27     // FIXME: These traits and enum and possible numerous switch(kind)
28     // block may be replaced with a special Handler<T> object or with
29     // a double dispatch
30     enum class ArgKind: int
31     {
32         OPAQUE_VAL,   // Unknown, generic, opaque-to-GAPI data type - STATIC
33                       // Note: OPAQUE is sometimes defined in Win sys headers
34 #if !defined(OPAQUE) && !defined(CV_DOXYGEN)
35         OPAQUE = OPAQUE_VAL,  // deprecated value used for compatibility, use OPAQUE_VAL instead
36 #endif
37         GOBJREF,      // <internal> reference to object
38         GMAT,         // a cv::GMat
39         GMATP,        // a cv::GMatP
40         GFRAME,       // a cv::GFrame
41         GSCALAR,      // a cv::GScalar
42         GARRAY,       // a cv::GArrayU  (note - exactly GArrayU,  not GArray<T>!)
43         GOPAQUE,      // a cv::GOpaqueU (note - exactly GOpaqueU, not GOpaque<T>!)
44     };
45
46     template<typename T>
47     constexpr const char* meta_to_string() noexcept;
48     template<>
49     constexpr const char* meta_to_string<cv::GMatDesc>() noexcept { return "GMatDesc"; }
50     template<>
51     constexpr const char* meta_to_string<cv::GScalarDesc>() noexcept { return "GScalarDesc"; }
52     template<>
53     constexpr const char* meta_to_string<cv::GArrayDesc>() noexcept { return "GArrayDesc"; }
54     template<>
55     constexpr const char* meta_to_string<cv::GOpaqueDesc>() noexcept { return "GOpaqueDesc"; }
56     template<>
57     constexpr const char* meta_to_string<cv::GFrameDesc>() noexcept { return "GFrameDesc";}
58
59     // Describe G-API types (G-types) with traits.  Mostly used by
60     // cv::GArg to store meta information about types passed into
61     // operation arguments. Please note that cv::GComputation is
62     // defined on GProtoArgs, not GArgs!
63     template<typename T> struct GTypeTraits;
64     template<typename T> struct GTypeTraits
65     {
66         static constexpr const ArgKind kind = ArgKind::OPAQUE_VAL;
67         static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
68     };
69     template<>           struct GTypeTraits<cv::GMat>
70     {
71         static constexpr const ArgKind kind = ArgKind::GMAT;
72         static constexpr const GShape shape = GShape::GMAT;
73         static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
74     };
75     template<>           struct GTypeTraits<cv::GMatP>
76     {
77         static constexpr const ArgKind kind = ArgKind::GMATP;
78         static constexpr const GShape shape = GShape::GMAT;
79         static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
80     };
81     template<>           struct GTypeTraits<cv::GFrame>
82     {
83         static constexpr const ArgKind kind = ArgKind::GFRAME;
84         static constexpr const GShape shape = GShape::GFRAME;
85         static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
86     };
87     template<>           struct GTypeTraits<cv::GScalar>
88     {
89         static constexpr const ArgKind kind = ArgKind::GSCALAR;
90         static constexpr const GShape shape = GShape::GSCALAR;
91         static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
92     };
93     template<class T> struct GTypeTraits<cv::GArray<T> >
94     {
95         static constexpr const ArgKind kind = ArgKind::GARRAY;
96         static constexpr const GShape shape = GShape::GARRAY;
97         static constexpr const OpaqueKind op_kind = GOpaqueTraits<T>::kind;
98         using host_type  = std::vector<T>;
99         using strip_type = cv::detail::VectorRef;
100         static cv::detail::GArrayU   wrap_value(const cv::GArray<T>  &t) { return t.strip();}
101         static cv::detail::VectorRef wrap_in   (const std::vector<T> &t) { return detail::VectorRef(t); }
102         static cv::detail::VectorRef wrap_out  (      std::vector<T> &t) { return detail::VectorRef(t); }
103     };
104     template<class T> struct GTypeTraits<cv::GOpaque<T> >
105     {
106         static constexpr const ArgKind kind = ArgKind::GOPAQUE;
107         static constexpr const GShape shape = GShape::GOPAQUE;
108         static constexpr const OpaqueKind op_kind = GOpaqueTraits<T>::kind;
109         using host_type  = T;
110         using strip_type = cv::detail::OpaqueRef;
111         static cv::detail::GOpaqueU  wrap_value(const cv::GOpaque<T>  &t) { return t.strip();}
112         static cv::detail::OpaqueRef wrap_in   (const T &t) { return detail::OpaqueRef(t); }
113         static cv::detail::OpaqueRef wrap_out  (      T &t) { return detail::OpaqueRef(t); }
114     };
115
116     // Tests if Trait for type T requires extra marshalling ("custom wrap") or not.
117     // If Traits<T> has wrap_value() defined, it does.
118     template<class T> struct has_custom_wrap
119     {
120         template<class,class> class check;
121         template<typename C> static std::true_type  test(check<C, decltype(&GTypeTraits<C>::wrap_value)> *);
122         template<typename C> static std::false_type test(...);
123         using type = decltype(test<T>(nullptr));
124         static const constexpr bool value = std::is_same<std::true_type, decltype(test<T>(nullptr))>::value;
125     };
126
127     // Resolve a Host type back to its associated G-Type.
128     // FIXME: Probably it can be avoided
129     // FIXME: GMatP is not present here.
130     // (Actually these traits is used only to check
131     // if associated G-type has custom wrap functions
132     // and GMat behavior is correct for GMatP)
133     template<typename T> struct GTypeOf;
134 #if !defined(GAPI_STANDALONE)
135     template<>           struct GTypeOf<cv::UMat>              { using type = cv::GMat;      };
136 #endif // !defined(GAPI_STANDALONE)
137     template<>           struct GTypeOf<cv::Mat>               { using type = cv::GMat;      };
138     template<>           struct GTypeOf<cv::RMat>              { using type = cv::GMat;      };
139     template<>           struct GTypeOf<cv::Scalar>            { using type = cv::GScalar;   };
140     template<typename U> struct GTypeOf<std::vector<U> >       { using type = cv::GArray<U>; };
141     template<typename U> struct GTypeOf                        { using type = cv::GOpaque<U>;};
142     template<>           struct GTypeOf<cv::MediaFrame>        { using type = cv::GFrame;    };
143     // FIXME: This is not quite correct since IStreamSource may produce not only Mat but also Scalar
144     // and vector data. TODO: Extend the type dispatching on these types too.
145     template<>           struct GTypeOf<cv::gapi::wip::IStreamSource::Ptr> { using type = cv::GMat;};
146     template<class T> using g_type_of_t = typename GTypeOf<T>::type;
147
148     // Marshalling helper for G-types and its Host types. Helps G-API
149     // to store G types in internal generic containers for further
150     // processing. Implements the following callbacks:
151     //
152     // * wrap() - converts user-facing G-type into an internal one
153     //   for internal storage.
154     //   Used when G-API operation is instantiated (G<Kernel>::on(),
155     //   etc) during expressing a pipeline. Mostly returns input
156     //   value "as is" except the case when G-type is a template. For
157     //   template G-classes, calls custom wrap() from Traits.
158     //   The value returned by wrap() is then wrapped into GArg() and
159     //   stored in G-API metadata.
160     //
161     //   Example:
162     //   - cv::GMat arguments are passed as-is.
163     //   - integers, pointers, STL containers, user types are passed as-is.
164     //   - cv::GArray<T> is converted to cv::GArrayU.
165     //
166     // * wrap_in() / wrap_out() - convert Host type associated with
167     //   G-type to internal representation type.
168     //
169     //   - For "simple" (non-template) G-types, returns value as-is.
170     //     Example: cv::GMat has host type cv::Mat, when user passes a
171     //              cv::Mat, system stores it internally as cv::Mat.
172     //
173     //   - For "complex" (template) G-types, utilizes custom
174     //     wrap_in()/wrap_out() as described in Traits.
175     //     Example: cv::GArray<T> has host type std::vector<T>, when
176     //              user passes a std::vector<T>, system stores it
177     //              internally as VectorRef (with <T> stripped away).
178     template<typename T, class Custom = void> struct WrapValue
179     {
180         static auto wrap(const T& t) ->
181             typename std::remove_reference<T>::type
182         {
183             return static_cast<typename std::remove_reference<T>::type>(t);
184         }
185
186         template<typename U> static U  wrap_in (const U &u) { return  u;  }
187         template<typename U> static U* wrap_out(U &u)       { return &u;  }
188     };
189     template<typename T> struct WrapValue<T, typename std::enable_if<has_custom_wrap<T>::value>::type>
190     {
191         static auto wrap(const T& t) -> decltype(GTypeTraits<T>::wrap_value(t))
192         {
193             return GTypeTraits<T>::wrap_value(t);
194         }
195         template<typename U> static auto wrap_in (const U &u) -> typename GTypeTraits<T>::strip_type
196         {
197             return GTypeTraits<T>::wrap_in(u);
198         }
199         template<typename U> static auto wrap_out(U &u) -> typename GTypeTraits<T>::strip_type
200         {
201             return GTypeTraits<T>::wrap_out(u);
202         }
203     };
204
205     template<typename T> using wrap_gapi_helper = WrapValue<typename std::decay<T>::type>;
206     template<typename T> using wrap_host_helper = WrapValue<typename std::decay<g_type_of_t<T> >::type>;
207
208 // Union type for various user-defined type constructors (GArray<T>,
209 // GOpaque<T>, etc)
210 //
211 // TODO: Replace construct-only API with a more generic one (probably
212 //    with bits of introspection)
213 //
214 // Not required for non-user-defined types (GMat, GScalar, etc)
215 using HostCtor = util::variant
216     < util::monostate
217     , detail::ConstructVec
218     , detail::ConstructOpaque
219     >;
220
221 template<typename T> struct GObtainCtor {
222     static HostCtor get() { return HostCtor{}; }
223 };
224 template<typename T> struct GObtainCtor<GArray<T> > {
225     static HostCtor get() { return HostCtor{ConstructVec{&GArray<T>::VCtor}}; };
226 };
227 template<typename T> struct GObtainCtor<GOpaque<T> > {
228     static HostCtor get() { return HostCtor{ConstructOpaque{&GOpaque<T>::Ctor}}; };
229 };
230 } // namespace detail
231 } // namespace cv
232
233 #endif // OPENCV_GAPI_GTYPE_TRAITS_HPP