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