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