s11n.hpp 17 KB

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