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) 2020-2021 Intel Corporation
6 
7 #ifndef OPENCV_GAPI_S11N_HPP
8 #define OPENCV_GAPI_S11N_HPP
9 
10 #include <vector>
11 #include <map>
12 #include <unordered_map>
13 #include <opencv2/gapi/s11n/base.hpp>
14 #include <opencv2/gapi/gcomputation.hpp>
15 #include <opencv2/gapi/rmat.hpp>
16 
17 namespace cv {
18 namespace gapi {
19 
20 namespace detail {
21     GAPI_EXPORTS cv::GComputation getGraph(const std::vector<char> &p);
22 
23     GAPI_EXPORTS cv::GMetaArgs getMetaArgs(const std::vector<char> &p);
24 
25     GAPI_EXPORTS cv::GRunArgs getRunArgs(const std::vector<char> &p);
26 
27     GAPI_EXPORTS std::vector<std::string> getVectorOfStrings(const std::vector<char> &p);
28 
29     template<typename... Types>
30     cv::GCompileArgs getCompileArgs(const std::vector<char> &p);
31 
32     template<typename RMatAdapterType>
33     cv::GRunArgs getRunArgsWithRMats(const std::vector<char> &p);
34 } // namespace detail
35 
36 GAPI_EXPORTS std::vector<char> serialize(const cv::GComputation &c);
37 //namespace{
38 
39 template<typename T> static inline
40 T deserialize(const std::vector<char> &p);
41 
42 //} //ananymous namespace
43 
44 GAPI_EXPORTS std::vector<char> serialize(const cv::GCompileArgs&);
45 GAPI_EXPORTS std::vector<char> serialize(const cv::GMetaArgs&);
46 GAPI_EXPORTS std::vector<char> serialize(const cv::GRunArgs&);
47 GAPI_EXPORTS std::vector<char> serialize(const std::vector<std::string>&);
48 
49 template<> inline
deserialize(const std::vector<char> & p)50 cv::GComputation deserialize(const std::vector<char> &p) {
51     return detail::getGraph(p);
52 }
53 
54 template<> inline
deserialize(const std::vector<char> & p)55 cv::GMetaArgs deserialize(const std::vector<char> &p) {
56     return detail::getMetaArgs(p);
57 }
58 
59 template<> inline
deserialize(const std::vector<char> & p)60 cv::GRunArgs deserialize(const std::vector<char> &p) {
61     return detail::getRunArgs(p);
62 }
63 
64 template<> inline
deserialize(const std::vector<char> & p)65 std::vector<std::string> deserialize(const std::vector<char> &p) {
66     return detail::getVectorOfStrings(p);
67 }
68 
69 template<typename T, typename... Types> inline
70 typename std::enable_if<std::is_same<T, GCompileArgs>::value, GCompileArgs>::
deserialize(const std::vector<char> & p)71 type deserialize(const std::vector<char> &p) {
72     return detail::getCompileArgs<Types...>(p);
73 }
74 
75 template<typename T, typename RMatAdapterType> inline
76 typename std::enable_if<std::is_same<T, GRunArgs>::value, GRunArgs>::
deserialize(const std::vector<char> & p)77 type deserialize(const std::vector<char> &p) {
78     return detail::getRunArgsWithRMats<RMatAdapterType>(p);
79 }
80 } // namespace gapi
81 } // namespace cv
82 
83 namespace cv {
84 namespace gapi {
85 namespace s11n {
86 struct GAPI_EXPORTS IOStream {
87     virtual ~IOStream() = default;
88     // Define the native support for basic C++ types at the API level:
89     virtual IOStream& operator<< (bool) = 0;
90     virtual IOStream& operator<< (char) = 0;
91     virtual IOStream& operator<< (unsigned char) = 0;
92     virtual IOStream& operator<< (short) = 0;
93     virtual IOStream& operator<< (unsigned short) = 0;
94     virtual IOStream& operator<< (int) = 0;
95     virtual IOStream& operator<< (uint32_t) = 0;
96     virtual IOStream& operator<< (uint64_t) = 0;
97     virtual IOStream& operator<< (float) = 0;
98     virtual IOStream& operator<< (double) = 0;
99     virtual IOStream& operator<< (const std::string&) = 0;
100 };
101 
102 struct GAPI_EXPORTS IIStream {
103     virtual ~IIStream() = default;
104     virtual IIStream& operator>> (bool &) = 0;
105     virtual IIStream& operator>> (std::vector<bool>::reference) = 0;
106     virtual IIStream& operator>> (char &) = 0;
107     virtual IIStream& operator>> (unsigned char &) = 0;
108     virtual IIStream& operator>> (short &) = 0;
109     virtual IIStream& operator>> (unsigned short &) = 0;
110     virtual IIStream& operator>> (int &) = 0;
111     virtual IIStream& operator>> (float &) = 0;
112     virtual IIStream& operator>> (double &) = 0;
113     virtual IIStream& operator >> (uint32_t &) = 0;
114     virtual IIStream& operator >> (uint64_t &) = 0;
115     virtual IIStream& operator>> (std::string &) = 0;
116 };
117 
118 namespace detail {
119 GAPI_EXPORTS std::unique_ptr<IIStream> getInStream(const std::vector<char> &p);
120 } // namespace detail
121 
122 ////////////////////////////////////////////////////////////////////////////////
123 ////////////////////////////////////////////////////////////////////////////////
124 // S11N operators
125 // Note: operators for basic types are defined in IIStream/IOStream
126 
127 // OpenCV types ////////////////////////////////////////////////////////////////
128 
129 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Point &pt);
130 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::Point &pt);
131 
132 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Point2f &pt);
133 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::Point2f &pt);
134 
135 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Size &sz);
136 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::Size &sz);
137 
138 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Rect &rc);
139 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::Rect &rc);
140 
141 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Scalar &s);
142 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::Scalar &s);
143 
144 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Mat &m);
145 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::Mat &m);
146 
147 // FIXME: for GRunArgs serailization
148 #if !defined(GAPI_STANDALONE)
149 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::UMat &);
150 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::UMat &);
151 #endif // !defined(GAPI_STANDALONE)
152 
153 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::RMat &r);
154 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::RMat &r);
155 
156 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::gapi::wip::IStreamSource::Ptr &);
157 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::gapi::wip::IStreamSource::Ptr &);
158 
159 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::VectorRef &);
160 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::detail::VectorRef &);
161 
162 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::OpaqueRef &);
163 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::detail::OpaqueRef &);
164 
165 GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::MediaFrame &);
166 GAPI_EXPORTS IIStream& operator>> (IIStream& is,       cv::MediaFrame &);
167 
168 // Generic STL types ////////////////////////////////////////////////////////////////
169 template<typename K, typename V>
operator <<(IOStream & os,const std::map<K,V> & m)170 IOStream& operator<< (IOStream& os, const std::map<K, V> &m) {
171     const uint32_t sz = static_cast<uint32_t>(m.size());
172     os << sz;
173     for (const auto& it : m) os << it.first << it.second;
174     return os;
175 }
176 template<typename K, typename V>
operator >>(IIStream & is,std::map<K,V> & m)177 IIStream& operator>> (IIStream& is, std::map<K, V> &m) {
178     m.clear();
179     uint32_t sz = 0u;
180     is >> sz;
181     for (std::size_t i = 0; i < sz; ++i) {
182         K k{};
183         V v{};
184         is >> k >> v;
185         m[k] = v;
186     }
187     return is;
188 }
189 template<typename K, typename V>
operator <<(IOStream & os,const std::unordered_map<K,V> & m)190 IOStream& operator<< (IOStream& os, const std::unordered_map<K, V> &m) {
191     const uint32_t sz = static_cast<uint32_t>(m.size());
192     os << sz;
193     for (auto &&it : m) os << it.first << it.second;
194     return os;
195 }
196 template<typename K, typename V>
operator >>(IIStream & is,std::unordered_map<K,V> & m)197 IIStream& operator>> (IIStream& is, std::unordered_map<K, V> &m) {
198     m.clear();
199     uint32_t sz = 0u;
200     is >> sz;
201     for (std::size_t i = 0; i < sz; ++i) {
202         K k{};
203         V v{};
204         is >> k >> v;
205         m[k] = v;
206     }
207     return is;
208 }
209 template<typename T>
operator <<(IOStream & os,const std::vector<T> & ts)210 IOStream& operator<< (IOStream& os, const std::vector<T> &ts) {
211     const uint32_t sz = static_cast<uint32_t>(ts.size());
212     os << sz;
213     for (auto &&v : ts) os << v;
214     return os;
215 }
216 template<typename T>
operator >>(IIStream & is,std::vector<T> & ts)217 IIStream& operator>> (IIStream& is, std::vector<T> &ts) {
218     uint32_t sz = 0u;
219     is >> sz;
220     if (sz == 0u) {
221         ts.clear();
222     }
223     else {
224         ts.resize(sz);
225         for (std::size_t i = 0; i < sz; ++i) is >> ts[i];
226     }
227     return is;
228 }
229 
230 // Generic: variant serialization
231 namespace detail {
232 template<typename V>
put_v(IOStream &,const V &,std::size_t)233 IOStream& put_v(IOStream&, const V&, std::size_t) {
234     GAPI_Assert(false && "variant>>: requested index is invalid");
235 };
236 template<typename V, typename X, typename... Xs>
put_v(IOStream & os,const V & v,std::size_t x)237 IOStream& put_v(IOStream& os, const V& v, std::size_t x) {
238     return (x == 0u)
239         ? os << cv::util::get<X>(v)
240         : put_v<V, Xs...>(os, v, x-1);
241 }
242 template<typename V>
get_v(IIStream &,V &,std::size_t,std::size_t)243 IIStream& get_v(IIStream&, V&, std::size_t, std::size_t) {
244     GAPI_Assert(false && "variant<<: requested index is invalid");
245 }
246 template<typename V, typename X, typename... Xs>
get_v(IIStream & is,V & v,std::size_t i,std::size_t gi)247 IIStream& get_v(IIStream& is, V& v, std::size_t i, std::size_t gi) {
248     if (i == gi) {
249         X x{};
250         is >> x;
251         v = V{std::move(x)};
252         return is;
253     } else return get_v<V, Xs...>(is, v, i+1, gi);
254 }
255 } // namespace detail
256 
257 template<typename... Ts>
operator <<(IOStream & os,const cv::util::variant<Ts...> & v)258 IOStream& operator<< (IOStream& os, const cv::util::variant<Ts...> &v) {
259     os << static_cast<uint32_t>(v.index());
260     return detail::put_v<cv::util::variant<Ts...>, Ts...>(os, v, v.index());
261 }
262 template<typename... Ts>
operator >>(IIStream & is,cv::util::variant<Ts...> & v)263 IIStream& operator>> (IIStream& is, cv::util::variant<Ts...> &v) {
264     int idx = -1;
265     is >> idx;
266     GAPI_Assert(idx >= 0 && idx < (int)sizeof...(Ts));
267     return detail::get_v<cv::util::variant<Ts...>, Ts...>(is, v, 0u, idx);
268 }
269 
270 // FIXME: consider a better solution
271 template<typename... Ts>
getRunArgByIdx(IIStream & is,cv::util::variant<Ts...> & v,uint32_t idx)272 void getRunArgByIdx (IIStream& is, cv::util::variant<Ts...> &v, uint32_t idx) {
273     is = detail::get_v<cv::util::variant<Ts...>, Ts...>(is, v, 0u, idx);
274 }
275 } // namespace s11n
276 
277 namespace detail
278 {
279 template<typename T> struct try_deserialize_comparg;
280 
281 template<> struct try_deserialize_comparg<std::tuple<>> {
282 static cv::util::optional<GCompileArg> exec(const std::string&, cv::gapi::s11n::IIStream&) {
283         return { };
284     }
285 };
286 
287 template<typename T, typename... Types>
288 struct try_deserialize_comparg<std::tuple<T, Types...>> {
execcv::gapi::detail::try_deserialize_comparg289 static cv::util::optional<GCompileArg> exec(const std::string& tag, cv::gapi::s11n::IIStream& is) {
290     if (tag == cv::detail::CompileArgTag<T>::tag()) {
291         static_assert(cv::gapi::s11n::detail::has_S11N_spec<T>::value,
292             "cv::gapi::deserialize<GCompileArgs, Types...> expects Types to have S11N "
293             "specializations with deserialization callbacks!");
294         return cv::util::optional<GCompileArg>(
295             GCompileArg { cv::gapi::s11n::detail::S11N<T>::deserialize(is) });
296     }
297     return try_deserialize_comparg<std::tuple<Types...>>::exec(tag, is);
298 }
299 };
300 
301 template<typename T> struct deserialize_runarg;
302 
303 template<typename RMatAdapterType>
304 struct deserialize_runarg {
execcv::gapi::detail::deserialize_runarg305 static GRunArg exec(cv::gapi::s11n::IIStream& is, uint32_t idx) {
306     if (idx == GRunArg::index_of<RMat>()) {
307         auto ptr = std::make_shared<RMatAdapterType>();
308         ptr->deserialize(is);
309         return GRunArg { RMat(std::move(ptr)) };
310     } else { // non-RMat arg - use default deserialization
311         GRunArg arg;
312         getRunArgByIdx(is, arg, idx);
313         return arg;
314     }
315 }
316 };
317 
318 template<typename... Types>
tryDeserializeCompArg(const std::string & tag,const std::vector<char> & sArg)319 inline cv::util::optional<GCompileArg> tryDeserializeCompArg(const std::string& tag,
320                                                              const std::vector<char>& sArg) {
321     std::unique_ptr<cv::gapi::s11n::IIStream> pArgIs = cv::gapi::s11n::detail::getInStream(sArg);
322     return try_deserialize_comparg<std::tuple<Types...>>::exec(tag, *pArgIs);
323 }
324 
325 template<typename... Types>
getCompileArgs(const std::vector<char> & sArgs)326 cv::GCompileArgs getCompileArgs(const std::vector<char> &sArgs) {
327     cv::GCompileArgs args;
328 
329     std::unique_ptr<cv::gapi::s11n::IIStream> pIs = cv::gapi::s11n::detail::getInStream(sArgs);
330     cv::gapi::s11n::IIStream& is = *pIs;
331 
332     uint32_t sz = 0;
333     is >> sz;
334     for (uint32_t i = 0; i < sz; ++i) {
335         std::string tag;
336         is >> tag;
337 
338         std::vector<char> sArg;
339         is >> sArg;
340 
341         cv::util::optional<GCompileArg> dArg =
342             cv::gapi::detail::tryDeserializeCompArg<Types...>(tag, sArg);
343 
344         if (dArg.has_value())
345         {
346             args.push_back(dArg.value());
347         }
348     }
349 
350     return args;
351 }
352 
353 template<typename RMatAdapterType>
getRunArgsWithRMats(const std::vector<char> & p)354 cv::GRunArgs getRunArgsWithRMats(const std::vector<char> &p) {
355     std::unique_ptr<cv::gapi::s11n::IIStream> pIs = cv::gapi::s11n::detail::getInStream(p);
356     cv::gapi::s11n::IIStream& is = *pIs;
357     cv::GRunArgs args;
358 
359     uint32_t sz = 0;
360     is >> sz;
361     for (uint32_t i = 0; i < sz; ++i) {
362         uint32_t idx = 0;
363         is >> idx;
364         args.push_back(cv::gapi::detail::deserialize_runarg<RMatAdapterType>::exec(is, idx));
365     }
366 
367     return args;
368 }
369 } // namespace detail
370 } // namespace gapi
371 } // namespace cv
372 
373 #endif // OPENCV_GAPI_S11N_HPP
374