s11n.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  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. #ifndef OPENCV_GAPI_S11N_HPP
  7. #define OPENCV_GAPI_S11N_HPP
  8. #include <vector>
  9. #include <map>
  10. #include <unordered_map>
  11. #include <opencv2/gapi/s11n/base.hpp>
  12. #include <opencv2/gapi/gcomputation.hpp>
  13. #include <opencv2/gapi/rmat.hpp>
  14. #include <opencv2/gapi/media.hpp>
  15. #include <opencv2/gapi/util/util.hpp>
  16. // FIXME: caused by deserialize_runarg
  17. #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
  18. #pragma warning(disable: 4702)
  19. #endif
  20. namespace cv {
  21. namespace gapi {
  22. /**
  23. * \addtogroup gapi_serialization
  24. * @{
  25. */
  26. namespace detail {
  27. GAPI_EXPORTS cv::GComputation getGraph(const std::vector<char> &bytes);
  28. GAPI_EXPORTS cv::GMetaArgs getMetaArgs(const std::vector<char> &bytes);
  29. GAPI_EXPORTS cv::GRunArgs getRunArgs(const std::vector<char> &bytes);
  30. GAPI_EXPORTS std::vector<std::string> getVectorOfStrings(const std::vector<char> &bytes);
  31. template<typename... Types>
  32. cv::GCompileArgs getCompileArgs(const std::vector<char> &bytes);
  33. template<typename... AdapterType>
  34. cv::GRunArgs getRunArgsWithAdapters(const std::vector<char> &bytes);
  35. } // namespace detail
  36. /** @brief Serialize a graph represented by GComputation into an array of bytes.
  37. *
  38. * Check different overloads for more examples.
  39. * @param c GComputation to serialize.
  40. * @return serialized vector of bytes.
  41. */
  42. GAPI_EXPORTS std::vector<char> serialize(const cv::GComputation &c);
  43. /** @overload
  44. * @param ca GCompileArgs to serialize.
  45. */
  46. GAPI_EXPORTS std::vector<char> serialize(const cv::GCompileArgs& ca);
  47. /** @overload
  48. * @param ma GMetaArgs to serialize.
  49. */
  50. GAPI_EXPORTS std::vector<char> serialize(const cv::GMetaArgs& ma);
  51. /** @overload
  52. * @param ra GRunArgs to serialize.
  53. */
  54. GAPI_EXPORTS std::vector<char> serialize(const cv::GRunArgs& ra);
  55. /** @overload
  56. * @param vs std::vector<std::string> to serialize.
  57. */
  58. GAPI_EXPORTS std::vector<char> serialize(const std::vector<std::string>& vs);
  59. /**
  60. * @private
  61. */
  62. template<typename T> static inline
  63. T deserialize(const std::vector<char> &bytes);
  64. /** @brief Deserialize GComputation from a byte array.
  65. *
  66. * Check different overloads for more examples.
  67. * @param bytes serialized vector of bytes.
  68. * @return deserialized GComputation object.
  69. */
  70. template<> inline
  71. cv::GComputation deserialize(const std::vector<char> &bytes) {
  72. return detail::getGraph(bytes);
  73. }
  74. /** @brief Deserialize GMetaArgs from a byte array.
  75. *
  76. * Check different overloads for more examples.
  77. * @param bytes serialized vector of bytes.
  78. * @return deserialized GMetaArgs object.
  79. */
  80. template<> inline
  81. cv::GMetaArgs deserialize(const std::vector<char> &bytes) {
  82. return detail::getMetaArgs(bytes);
  83. }
  84. /** @brief Deserialize GRunArgs from a byte array.
  85. *
  86. * Check different overloads for more examples.
  87. * @param bytes serialized vector of bytes.
  88. * @return deserialized GRunArgs object.
  89. */
  90. template<> inline
  91. cv::GRunArgs deserialize(const std::vector<char> &bytes) {
  92. return detail::getRunArgs(bytes);
  93. }
  94. /** @brief Deserialize std::vector<std::string> from a byte array.
  95. *
  96. * Check different overloads for more examples.
  97. * @param bytes serialized vector of bytes.
  98. * @return deserialized std::vector<std::string> object.
  99. */
  100. template<> inline
  101. std::vector<std::string> deserialize(const std::vector<char> &bytes) {
  102. return detail::getVectorOfStrings(bytes);
  103. }
  104. /**
  105. * @brief Deserialize GCompileArgs which types were specified in the template from a byte array.
  106. *
  107. * @note cv::gapi::s11n::detail::S11N template specialization must be provided to make a custom type
  108. * in GCompileArgs deserializable.
  109. *
  110. * @param bytes vector of bytes to deserialize GCompileArgs object from.
  111. * @return GCompileArgs object.
  112. * @see GCompileArgs cv::gapi::s11n::detail::S11N
  113. */
  114. template<typename T, typename... Types> inline
  115. typename std::enable_if<std::is_same<T, GCompileArgs>::value, GCompileArgs>::
  116. type deserialize(const std::vector<char> &bytes) {
  117. return detail::getCompileArgs<Types...>(bytes);
  118. }
  119. /**
  120. * @brief Deserialize GRunArgs including RMat and MediaFrame objects if any from a byte array.
  121. *
  122. * Adapter types are specified in the template.
  123. * @note To be used properly specified adapter types must overload their deserialize() method.
  124. * @param bytes vector of bytes to deserialize GRunArgs object from.
  125. * @return GRunArgs including RMat and MediaFrame objects if any.
  126. * @see RMat MediaFrame
  127. */
  128. template<typename T, typename AtLeastOneAdapterT, typename... AdapterTypes> inline
  129. typename std::enable_if<std::is_same<T, GRunArgs>::value, GRunArgs>::
  130. type deserialize(const std::vector<char> &bytes) {
  131. return detail::getRunArgsWithAdapters<AtLeastOneAdapterT, AdapterTypes...>(bytes);
  132. }
  133. } // namespace gapi
  134. } // namespace cv
  135. namespace cv {
  136. namespace gapi {
  137. namespace s11n {
  138. /** @brief This structure is an interface for serialization routines.
  139. *
  140. * It's main purpose is to provide multiple overloads for operator<<()
  141. * with basic C++ in addition to OpenCV/G-API types.
  142. *
  143. * This sctructure can be inherited and further extended with additional types.
  144. *
  145. * For example, it is utilized in cv::gapi::s11n::detail::S11N as input parameter
  146. * in serialize() method.
  147. */
  148. struct GAPI_EXPORTS IOStream {
  149. virtual ~IOStream() = default;
  150. // Define the native support for basic C++ types at the API level:
  151. virtual IOStream& operator<< (bool) = 0;
  152. virtual IOStream& operator<< (char) = 0;
  153. virtual IOStream& operator<< (unsigned char) = 0;
  154. virtual IOStream& operator<< (short) = 0;
  155. virtual IOStream& operator<< (unsigned short) = 0;
  156. virtual IOStream& operator<< (int) = 0;
  157. virtual IOStream& operator<< (uint32_t) = 0;
  158. virtual IOStream& operator<< (uint64_t) = 0;
  159. virtual IOStream& operator<< (float) = 0;
  160. virtual IOStream& operator<< (double) = 0;
  161. virtual IOStream& operator<< (const std::string&) = 0;
  162. };
  163. /** @brief This structure is an interface for deserialization routines.
  164. *
  165. * It's main purpose is to provide multiple overloads for operator>>()
  166. * with basic C++ in addition to OpenCV/G-API types.
  167. *
  168. * This structure can be inherited and further extended with additional types.
  169. *
  170. * For example, it is utilized in cv::gapi::s11n::detail::S11N as input parameter
  171. * in deserialize() method.
  172. */
  173. struct GAPI_EXPORTS IIStream {
  174. virtual ~IIStream() = default;
  175. virtual IIStream& operator>> (bool &) = 0;
  176. virtual IIStream& operator>> (std::vector<bool>::reference) = 0;
  177. virtual IIStream& operator>> (char &) = 0;
  178. virtual IIStream& operator>> (unsigned char &) = 0;
  179. virtual IIStream& operator>> (short &) = 0;
  180. virtual IIStream& operator>> (unsigned short &) = 0;
  181. virtual IIStream& operator>> (int &) = 0;
  182. virtual IIStream& operator>> (float &) = 0;
  183. virtual IIStream& operator>> (double &) = 0;
  184. virtual IIStream& operator >> (uint32_t &) = 0;
  185. virtual IIStream& operator >> (uint64_t &) = 0;
  186. virtual IIStream& operator>> (std::string &) = 0;
  187. };
  188. namespace detail {
  189. GAPI_EXPORTS std::unique_ptr<IIStream> getInStream(const std::vector<char> &bytes);
  190. } // namespace detail
  191. ////////////////////////////////////////////////////////////////////////////////
  192. ////////////////////////////////////////////////////////////////////////////////
  193. // S11N operators
  194. // Note: operators for basic types are defined in IIStream/IOStream
  195. // OpenCV types ////////////////////////////////////////////////////////////////
  196. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Point &pt);
  197. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Point &pt);
  198. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Point2f &pt);
  199. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Point2f &pt);
  200. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Size &sz);
  201. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Size &sz);
  202. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Rect &rc);
  203. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Rect &rc);
  204. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Scalar &s);
  205. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Scalar &s);
  206. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Mat &m);
  207. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Mat &m);
  208. // FIXME: for GRunArgs serialization
  209. #if !defined(GAPI_STANDALONE)
  210. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::UMat & um);
  211. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::UMat & um);
  212. #endif // !defined(GAPI_STANDALONE)
  213. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::RMat &r);
  214. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::RMat &r);
  215. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::gapi::wip::IStreamSource::Ptr &issptr);
  216. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::gapi::wip::IStreamSource::Ptr &issptr);
  217. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::VectorRef &vr);
  218. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::VectorRef &vr);
  219. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::OpaqueRef &opr);
  220. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::OpaqueRef &opr);
  221. /// @private -- Exclude this function from OpenCV documentation
  222. GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::MediaFrame &mf);
  223. /// @private -- Exclude this function from OpenCV documentation
  224. GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::MediaFrame &mf);
  225. // Generic STL types ////////////////////////////////////////////////////////////////
  226. template<typename K, typename V>
  227. IOStream& operator<< (IOStream& os, const std::map<K, V> &m) {
  228. const uint32_t sz = static_cast<uint32_t>(m.size());
  229. os << sz;
  230. for (const auto& it : m) os << it.first << it.second;
  231. return os;
  232. }
  233. template<typename K, typename V>
  234. IIStream& operator>> (IIStream& is, std::map<K, V> &m) {
  235. m.clear();
  236. uint32_t sz = 0u;
  237. is >> sz;
  238. for (std::size_t i = 0; i < sz; ++i) {
  239. K k{};
  240. V v{};
  241. is >> k >> v;
  242. m[k] = v;
  243. }
  244. return is;
  245. }
  246. template<typename K, typename V>
  247. IOStream& operator<< (IOStream& os, const std::unordered_map<K, V> &m) {
  248. const uint32_t sz = static_cast<uint32_t>(m.size());
  249. os << sz;
  250. for (auto &&it : m) os << it.first << it.second;
  251. return os;
  252. }
  253. template<typename K, typename V>
  254. IIStream& operator>> (IIStream& is, std::unordered_map<K, V> &m) {
  255. m.clear();
  256. uint32_t sz = 0u;
  257. is >> sz;
  258. for (std::size_t i = 0; i < sz; ++i) {
  259. K k{};
  260. V v{};
  261. is >> k >> v;
  262. m[k] = v;
  263. }
  264. return is;
  265. }
  266. template<typename T>
  267. IOStream& operator<< (IOStream& os, const std::vector<T> &ts) {
  268. const uint32_t sz = static_cast<uint32_t>(ts.size());
  269. os << sz;
  270. for (auto &&v : ts) os << v;
  271. return os;
  272. }
  273. template<typename T>
  274. IIStream& operator>> (IIStream& is, std::vector<T> &ts) {
  275. uint32_t sz = 0u;
  276. is >> sz;
  277. if (sz == 0u) {
  278. ts.clear();
  279. }
  280. else {
  281. ts.resize(sz);
  282. for (std::size_t i = 0; i < sz; ++i) is >> ts[i];
  283. }
  284. return is;
  285. }
  286. // Generic: variant serialization
  287. namespace detail {
  288. template<typename V>
  289. IOStream& put_v(IOStream&, const V&, std::size_t) {
  290. GAPI_Assert(false && "variant>>: requested index is invalid");
  291. };
  292. template<typename V, typename X, typename... Xs>
  293. IOStream& put_v(IOStream& os, const V& v, std::size_t x) {
  294. return (x == 0u)
  295. ? os << cv::util::get<X>(v)
  296. : put_v<V, Xs...>(os, v, x-1);
  297. }
  298. template<typename V>
  299. IIStream& get_v(IIStream&, V&, std::size_t, std::size_t) {
  300. GAPI_Assert(false && "variant<<: requested index is invalid");
  301. }
  302. template<typename V, typename X, typename... Xs>
  303. IIStream& get_v(IIStream& is, V& v, std::size_t i, std::size_t gi) {
  304. if (i == gi) {
  305. X x{};
  306. is >> x;
  307. v = V{std::move(x)};
  308. return is;
  309. } else return get_v<V, Xs...>(is, v, i+1, gi);
  310. }
  311. } // namespace detail
  312. //! @overload
  313. template<typename... Ts>
  314. IOStream& operator<< (IOStream& os, const cv::util::variant<Ts...> &v) {
  315. os << static_cast<uint32_t>(v.index());
  316. return detail::put_v<cv::util::variant<Ts...>, Ts...>(os, v, v.index());
  317. }
  318. //! @overload
  319. template<typename... Ts>
  320. IIStream& operator>> (IIStream& is, cv::util::variant<Ts...> &v) {
  321. int idx = -1;
  322. is >> idx;
  323. GAPI_Assert(idx >= 0 && idx < (int)sizeof...(Ts));
  324. return detail::get_v<cv::util::variant<Ts...>, Ts...>(is, v, 0u, idx);
  325. }
  326. // FIXME: consider a better solution
  327. /// @private -- Exclude this function from OpenCV documentation
  328. template<typename... Ts>
  329. void getRunArgByIdx (IIStream& is, cv::util::variant<Ts...> &v, uint32_t idx) {
  330. is = detail::get_v<cv::util::variant<Ts...>, Ts...>(is, v, 0u, idx);
  331. }
  332. } // namespace s11n
  333. namespace detail
  334. {
  335. template<typename T> struct try_deserialize_comparg;
  336. template<> struct try_deserialize_comparg<std::tuple<>> {
  337. static cv::util::optional<GCompileArg> exec(const std::string&, cv::gapi::s11n::IIStream&) {
  338. return { };
  339. }
  340. };
  341. template<typename T, typename... Types>
  342. struct try_deserialize_comparg<std::tuple<T, Types...>> {
  343. static cv::util::optional<GCompileArg> exec(const std::string& tag, cv::gapi::s11n::IIStream& is) {
  344. if (tag == cv::detail::CompileArgTag<T>::tag()) {
  345. static_assert(cv::gapi::s11n::detail::has_S11N_spec<T>::value,
  346. "cv::gapi::deserialize<GCompileArgs, Types...> expects Types to have S11N "
  347. "specializations with deserialization callbacks!");
  348. return cv::util::optional<GCompileArg>(
  349. GCompileArg { cv::gapi::s11n::detail::S11N<T>::deserialize(is) });
  350. }
  351. return try_deserialize_comparg<std::tuple<Types...>>::exec(tag, is);
  352. }
  353. };
  354. template<typename ...T>
  355. struct deserialize_arg_with_adapter;
  356. template<typename RA, typename TA>
  357. struct deserialize_arg_with_adapter<RA, TA> {
  358. static GRunArg exec(cv::gapi::s11n::IIStream& is) {
  359. std::unique_ptr<TA> ptr(new TA);
  360. ptr->deserialize(is);
  361. return GRunArg { RA(std::move(ptr)) };
  362. }
  363. };
  364. template<typename RA>
  365. struct deserialize_arg_with_adapter<RA, void> {
  366. static GRunArg exec(cv::gapi::s11n::IIStream&) {
  367. GAPI_Assert(false && "No suitable adapter class found during RMat/MediaFrame deserialization. "
  368. "Please, make sure you've passed them in cv::gapi::deserialize() template");
  369. return GRunArg{};
  370. }
  371. };
  372. template<typename... Types>
  373. struct deserialize_runarg {
  374. static GRunArg exec(cv::gapi::s11n::IIStream& is, uint32_t idx) {
  375. if (idx == GRunArg::index_of<RMat>()) {
  376. // Type or void (if not found)
  377. using TA = typename cv::util::find_adapter_impl<RMat::IAdapter, Types...>::type;
  378. return deserialize_arg_with_adapter<RMat, TA>::exec(is);
  379. } else if (idx == GRunArg::index_of<MediaFrame>()) {
  380. // Type or void (if not found)
  381. using TA = typename cv::util::find_adapter_impl<MediaFrame::IAdapter, Types...>::type;
  382. return deserialize_arg_with_adapter<MediaFrame, TA>::exec(is);
  383. } else { // not an adapter holding type runarg - use default deserialization
  384. GRunArg arg;
  385. getRunArgByIdx(is, arg, idx);
  386. return arg;
  387. }
  388. }
  389. };
  390. template<typename... Types>
  391. inline cv::util::optional<GCompileArg> tryDeserializeCompArg(const std::string& tag,
  392. const std::vector<char>& sArg) {
  393. std::unique_ptr<cv::gapi::s11n::IIStream> pArgIs = cv::gapi::s11n::detail::getInStream(sArg);
  394. return try_deserialize_comparg<std::tuple<Types...>>::exec(tag, *pArgIs);
  395. }
  396. template<typename... Types>
  397. cv::GCompileArgs getCompileArgs(const std::vector<char> &sArgs) {
  398. cv::GCompileArgs args;
  399. std::unique_ptr<cv::gapi::s11n::IIStream> pIs = cv::gapi::s11n::detail::getInStream(sArgs);
  400. cv::gapi::s11n::IIStream& is = *pIs;
  401. uint32_t sz = 0;
  402. is >> sz;
  403. for (uint32_t i = 0; i < sz; ++i) {
  404. std::string tag;
  405. is >> tag;
  406. std::vector<char> sArg;
  407. is >> sArg;
  408. cv::util::optional<GCompileArg> dArg =
  409. cv::gapi::detail::tryDeserializeCompArg<Types...>(tag, sArg);
  410. if (dArg.has_value())
  411. {
  412. args.push_back(dArg.value());
  413. }
  414. }
  415. return args;
  416. }
  417. template<typename... AdapterTypes>
  418. cv::GRunArgs getRunArgsWithAdapters(const std::vector<char> &bytes) {
  419. std::unique_ptr<cv::gapi::s11n::IIStream> pIs = cv::gapi::s11n::detail::getInStream(bytes);
  420. cv::gapi::s11n::IIStream& is = *pIs;
  421. cv::GRunArgs args;
  422. uint32_t sz = 0;
  423. is >> sz;
  424. for (uint32_t i = 0; i < sz; ++i) {
  425. uint32_t idx = 0;
  426. is >> idx;
  427. args.push_back(cv::gapi::detail::deserialize_runarg<AdapterTypes...>::exec(is, idx));
  428. }
  429. return args;
  430. }
  431. } // namespace detail
  432. /** @} */
  433. } // namespace gapi
  434. } // namespace cv
  435. #endif // OPENCV_GAPI_S11N_HPP