gstreaming.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  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-2021 Intel Corporation
  6. #ifndef OPENCV_GAPI_GSTREAMING_COMPILED_HPP
  7. #define OPENCV_GAPI_GSTREAMING_COMPILED_HPP
  8. #include <memory>
  9. #include <vector>
  10. #include <opencv2/gapi/opencv_includes.hpp>
  11. #include <opencv2/gapi/own/assert.hpp>
  12. #include <opencv2/gapi/util/optional.hpp>
  13. #include <opencv2/gapi/garg.hpp>
  14. #include <opencv2/gapi/streaming/source.hpp>
  15. namespace cv {
  16. template<class T> using optional = cv::util::optional<T>;
  17. namespace detail {
  18. template<typename T> struct wref_spec {
  19. using type = T;
  20. };
  21. template<typename T> struct wref_spec<std::vector<T> > {
  22. using type = T;
  23. };
  24. template<typename RefHolder>
  25. struct OptRef {
  26. struct OptHolder {
  27. virtual void mov(RefHolder &h) = 0;
  28. virtual void reset() = 0;
  29. virtual ~OptHolder() = default;
  30. using Ptr = std::shared_ptr<OptHolder>;
  31. };
  32. template<class T> struct Holder final: OptHolder {
  33. std::reference_wrapper<cv::optional<T> > m_opt_ref;
  34. explicit Holder(cv::optional<T>& opt) : m_opt_ref(std::ref(opt)) {
  35. }
  36. virtual void mov(RefHolder &h) override {
  37. using U = typename wref_spec<T>::type;
  38. m_opt_ref.get() = cv::util::make_optional(std::move(h.template wref<U>()));
  39. }
  40. virtual void reset() override {
  41. m_opt_ref.get().reset();
  42. }
  43. };
  44. template<class T>
  45. explicit OptRef(cv::optional<T>& t) : m_opt{new Holder<T>(t)} {}
  46. void mov(RefHolder &h) { m_opt->mov(h); }
  47. void reset() { m_opt->reset();}
  48. private:
  49. typename OptHolder::Ptr m_opt;
  50. };
  51. using OptionalVectorRef = OptRef<cv::detail::VectorRef>;
  52. using OptionalOpaqueRef = OptRef<cv::detail::OpaqueRef>;
  53. } // namespace detail
  54. // TODO: Keep it in sync with GRunArgP (derive the type automatically?)
  55. using GOptRunArgP = util::variant<
  56. optional<cv::Mat>*,
  57. optional<cv::RMat>*,
  58. optional<cv::MediaFrame>*,
  59. optional<cv::Scalar>*,
  60. cv::detail::OptionalVectorRef,
  61. cv::detail::OptionalOpaqueRef
  62. >;
  63. using GOptRunArgsP = std::vector<GOptRunArgP>;
  64. using GOptRunArg = util::variant<
  65. optional<cv::Mat>,
  66. optional<cv::RMat>,
  67. optional<cv::MediaFrame>,
  68. optional<cv::Scalar>,
  69. optional<cv::detail::VectorRef>,
  70. optional<cv::detail::OpaqueRef>
  71. >;
  72. using GOptRunArgs = std::vector<GOptRunArg>;
  73. namespace detail {
  74. template<typename T> inline GOptRunArgP wrap_opt_arg(optional<T>& arg) {
  75. // By default, T goes to an OpaqueRef. All other types are specialized
  76. return GOptRunArgP{OptionalOpaqueRef(arg)};
  77. }
  78. template<typename T> inline GOptRunArgP wrap_opt_arg(optional<std::vector<T> >& arg) {
  79. return GOptRunArgP{OptionalVectorRef(arg)};
  80. }
  81. template<> inline GOptRunArgP wrap_opt_arg(optional<cv::Mat> &m) {
  82. return GOptRunArgP{&m};
  83. }
  84. template<> inline GOptRunArgP wrap_opt_arg(optional<cv::RMat> &m) {
  85. return GOptRunArgP{&m};
  86. }
  87. template<> inline GOptRunArgP wrap_opt_arg(optional<cv::MediaFrame> &f) {
  88. return GOptRunArgP{&f};
  89. }
  90. template<> inline GOptRunArgP wrap_opt_arg(optional<cv::Scalar> &s) {
  91. return GOptRunArgP{&s};
  92. }
  93. } // namespace detail
  94. // Now cv::gout() may produce an empty vector (see "dynamic graphs"), so
  95. // there may be a conflict between these two. State here that Opt version
  96. // _must_ have at least one input for this overload
  97. template<typename T, typename... Ts>
  98. inline GOptRunArgsP gout(optional<T>&arg, optional<Ts>&... args)
  99. {
  100. return GOptRunArgsP{ detail::wrap_opt_arg(arg), detail::wrap_opt_arg(args)... };
  101. }
  102. /**
  103. * \addtogroup gapi_main_classes
  104. * @{
  105. */
  106. /**
  107. * @brief Represents a computation (graph) compiled for streaming.
  108. *
  109. * This class represents a product of graph compilation (calling
  110. * cv::GComputation::compileStreaming()). Objects of this class
  111. * actually do stream processing, and the whole pipeline execution
  112. * complexity is incapsulated into objects of this class. Execution
  113. * model has two levels: at the very top, the execution of a
  114. * heterogeneous graph is aggressively pipelined; at the very bottom
  115. * the execution of every internal block is determined by its
  116. * associated backend. Backends are selected based on kernel packages
  117. * passed via compilation arguments ( see @ref gapi_compile_args,
  118. * GNetworkPackage, GKernelPackage for details).
  119. *
  120. * GStreamingCompiled objects have a "player" semantics -- there are
  121. * methods like start() and stop(). GStreamingCompiled has a full
  122. * control over a videostream and so is stateful. You need to specify the
  123. * input stream data using setSource() and then call start() to
  124. * actually start processing. After that, use pull() or try_pull() to
  125. * obtain next processed data frame from the graph in a blocking or
  126. * non-blocking way, respectively.
  127. *
  128. * Currently a single GStreamingCompiled can process only one video
  129. * streat at time. Produce multiple GStreamingCompiled objects to run the
  130. * same graph on multiple video streams.
  131. *
  132. * @sa GCompiled
  133. */
  134. class GAPI_EXPORTS_W_SIMPLE GStreamingCompiled
  135. {
  136. public:
  137. class GAPI_EXPORTS Priv;
  138. GAPI_WRAP GStreamingCompiled();
  139. // FIXME: More overloads?
  140. /**
  141. * @brief Specify the input data to GStreamingCompiled for
  142. * processing, a generic version.
  143. *
  144. * Use gin() to create an input parameter vector.
  145. *
  146. * Input vectors must have the same number of elements as defined
  147. * in the cv::GComputation protocol (at the moment of its
  148. * construction). Shapes of elements also must conform to protocol
  149. * (e.g. cv::Mat needs to be passed where cv::GMat has been
  150. * declared as input, and so on). Run-time exception is generated
  151. * on type mismatch.
  152. *
  153. * In contrast with regular GCompiled, user can also pass an
  154. * object of type GVideoCapture for a GMat parameter of the parent
  155. * GComputation. The compiled pipeline will start fetching data
  156. * from that GVideoCapture and feeding it into the
  157. * pipeline. Pipeline stops when a GVideoCapture marks end of the
  158. * stream (or when stop() is called).
  159. *
  160. * Passing a regular Mat for a GMat parameter makes it "infinite"
  161. * source -- pipeline may run forever feeding with this Mat until
  162. * stopped explicitly.
  163. *
  164. * Currently only a single GVideoCapture is supported as input. If
  165. * the parent GComputation is declared with multiple input GMat's,
  166. * one of those can be specified as GVideoCapture but all others
  167. * must be regular Mat objects.
  168. *
  169. * Throws if pipeline is already running. Use stop() and then
  170. * setSource() to run the graph on a new video stream.
  171. *
  172. * @note This method is not thread-safe (with respect to the user
  173. * side) at the moment. Protect the access if
  174. * start()/stop()/setSource() may be called on the same object in
  175. * multiple threads in your application.
  176. *
  177. * @param ins vector of inputs to process.
  178. * @sa gin
  179. */
  180. void setSource(GRunArgs &&ins);
  181. /// @private -- Exclude this function from OpenCV documentation
  182. GAPI_WRAP void setSource(const cv::detail::ExtractArgsCallback& callback);
  183. /**
  184. * @brief Specify an input video stream for a single-input
  185. * computation pipeline.
  186. *
  187. * Throws if pipeline is already running. Use stop() and then
  188. * setSource() to run the graph on a new video stream.
  189. *
  190. * @overload
  191. * @param s a shared pointer to IStreamSource representing the
  192. * input video stream.
  193. */
  194. void setSource(const gapi::wip::IStreamSource::Ptr& s);
  195. /**
  196. * @brief Constructs and specifies an input video stream for a
  197. * single-input computation pipeline with the given parameters.
  198. *
  199. * Throws if pipeline is already running. Use stop() and then
  200. * setSource() to run the graph on a new video stream.
  201. *
  202. * @overload
  203. * @param args arguments used to construct and initialize a stream
  204. * source.
  205. */
  206. template<typename T, typename... Args>
  207. void setSource(Args&&... args) {
  208. setSource(cv::gapi::wip::make_src<T>(std::forward<Args>(args)...));
  209. }
  210. /**
  211. * @brief Start the pipeline execution.
  212. *
  213. * Use pull()/try_pull() to obtain data. Throws an exception if
  214. * a video source was not specified.
  215. *
  216. * setSource() must be called first, even if the pipeline has been
  217. * working already and then stopped (explicitly via stop() or due
  218. * stream completion)
  219. *
  220. * @note This method is not thread-safe (with respect to the user
  221. * side) at the moment. Protect the access if
  222. * start()/stop()/setSource() may be called on the same object in
  223. * multiple threads in your application.
  224. */
  225. GAPI_WRAP void start();
  226. /**
  227. * @brief Get the next processed frame from the pipeline.
  228. *
  229. * Use gout() to create an output parameter vector.
  230. *
  231. * Output vectors must have the same number of elements as defined
  232. * in the cv::GComputation protocol (at the moment of its
  233. * construction). Shapes of elements also must conform to protocol
  234. * (e.g. cv::Mat needs to be passed where cv::GMat has been
  235. * declared as output, and so on). Run-time exception is generated
  236. * on type mismatch.
  237. *
  238. * This method writes new data into objects passed via output
  239. * vector. If there is no data ready yet, this method blocks. Use
  240. * try_pull() if you need a non-blocking version.
  241. *
  242. * @param outs vector of output parameters to obtain.
  243. * @return true if next result has been obtained,
  244. * false marks end of the stream.
  245. */
  246. bool pull(cv::GRunArgsP &&outs);
  247. // NB: Used from python
  248. /// @private -- Exclude this function from OpenCV documentation
  249. GAPI_WRAP std::tuple<bool, cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>> pull();
  250. /**
  251. * @brief Get some next available data from the pipeline.
  252. *
  253. * This method takes a vector of cv::optional object. An object is
  254. * assigned to some value if this value is available (ready) at
  255. * the time of the call, and resets the object to empty() if it is
  256. * not.
  257. *
  258. * This is a blocking method which guarantees that some data has
  259. * been written to the output vector on return.
  260. *
  261. * Using this method only makes sense if the graph has
  262. * desynchronized parts (see cv::gapi::desync). If there is no
  263. * desynchronized parts in the graph, the behavior of this
  264. * method is identical to the regular pull() (all data objects are
  265. * produced synchronously in the output vector).
  266. *
  267. * Use gout() to create an output parameter vector.
  268. *
  269. * Output vectors must have the same number of elements as defined
  270. * in the cv::GComputation protocol (at the moment of its
  271. * construction). Shapes of elements also must conform to protocol
  272. * (e.g. cv::optional<cv::Mat> needs to be passed where cv::GMat
  273. * has been declared as output, and so on). Run-time exception is
  274. * generated on type mismatch.
  275. *
  276. * This method writes new data into objects passed via output
  277. * vector. If there is no data ready yet, this method blocks. Use
  278. * try_pull() if you need a non-blocking version.
  279. *
  280. * @param outs vector of output parameters to obtain.
  281. * @return true if next result has been obtained,
  282. * false marks end of the stream.
  283. *
  284. * @sa cv::gapi::desync
  285. */
  286. bool pull(cv::GOptRunArgsP &&outs);
  287. /**
  288. * @brief Try to get the next processed frame from the pipeline.
  289. *
  290. * Use gout() to create an output parameter vector.
  291. *
  292. * This method writes new data into objects passed via output
  293. * vector. If there is no data ready yet, the output vector
  294. * remains unchanged and false is returned.
  295. *
  296. * @return true if data has been obtained, and false if it was
  297. * not. Note: false here doesn't mark the end of the stream.
  298. */
  299. bool try_pull(cv::GRunArgsP &&outs);
  300. /**
  301. * @brief Stop (abort) processing the pipeline.
  302. *
  303. * Note - it is not pause but a complete stop. Calling start()
  304. * will cause G-API to start processing the stream from the early beginning.
  305. *
  306. * Throws if the pipeline is not running.
  307. */
  308. GAPI_WRAP void stop();
  309. /**
  310. * @brief Test if the pipeline is running.
  311. *
  312. * @note This method is not thread-safe (with respect to the user
  313. * side) at the moment. Protect the access if
  314. * start()/stop()/setSource() may be called on the same object in
  315. * multiple threads in your application.
  316. *
  317. * @return true if the current stream is not over yet.
  318. */
  319. GAPI_WRAP bool running() const;
  320. /// @private
  321. Priv& priv();
  322. /**
  323. * @brief Check if compiled object is valid (non-empty)
  324. *
  325. * @return true if the object is runnable (valid), false otherwise
  326. */
  327. explicit operator bool () const;
  328. /**
  329. * @brief Vector of metadata this graph was compiled for.
  330. *
  331. * @return Unless _reshape_ is not supported, return value is the
  332. * same vector which was passed to cv::GComputation::compile() to
  333. * produce this compiled object. Otherwise, it is the latest
  334. * metadata vector passed to reshape() (if that call was
  335. * successful).
  336. */
  337. const GMetaArgs& metas() const; // Meta passed to compile()
  338. /**
  339. * @brief Vector of metadata descriptions of graph outputs
  340. *
  341. * @return vector with formats/resolutions of graph's output
  342. * objects, auto-inferred from input metadata vector by
  343. * operations which form this computation.
  344. *
  345. * @note GCompiled objects produced from the same
  346. * cv::GComputiation graph with different input metas may return
  347. * different values in this vector.
  348. */
  349. const GMetaArgs& outMetas() const;
  350. protected:
  351. /// @private
  352. std::shared_ptr<Priv> m_priv;
  353. };
  354. /** @} */
  355. namespace gapi {
  356. /**
  357. * @brief This namespace contains G-API functions, structures, and
  358. * symbols related to the Streaming execution mode.
  359. *
  360. * Some of the operations defined in this namespace (e.g. size(),
  361. * BGR(), etc.) can be used in the traditional execution mode too.
  362. */
  363. namespace streaming {
  364. /**
  365. * @brief Specify queue capacity for streaming execution.
  366. *
  367. * In the streaming mode the pipeline steps are connected with queues
  368. * and this compile argument controls every queue's size.
  369. */
  370. struct GAPI_EXPORTS_W_SIMPLE queue_capacity
  371. {
  372. GAPI_WRAP
  373. explicit queue_capacity(size_t cap = 1) : capacity(cap) { };
  374. GAPI_PROP_RW
  375. size_t capacity;
  376. };
  377. /** @} */
  378. } // namespace streaming
  379. } // namespace gapi
  380. namespace detail
  381. {
  382. template<> struct CompileArgTag<cv::gapi::streaming::queue_capacity>
  383. {
  384. static const char* tag() { return "gapi.queue_capacity"; }
  385. };
  386. }
  387. }
  388. #endif // OPENCV_GAPI_GSTREAMING_COMPILED_HPP