cap.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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) 2019 Intel Corporation
  6. #ifndef OPENCV_GAPI_STREAMING_CAP_HPP
  7. #define OPENCV_GAPI_STREAMING_CAP_HPP
  8. /**
  9. * YOUR ATTENTION PLEASE!
  10. *
  11. * This is a header-only implementation of cv::VideoCapture-based
  12. * Stream source. It is not built by default with G-API as G-API
  13. * doesn't depend on videoio module.
  14. *
  15. * If you want to use it in your application, please make sure
  16. * videioio is available in your OpenCV package and is linked to your
  17. * application.
  18. *
  19. * Note for developers: please don't put videoio dependency in G-API
  20. * because of this file.
  21. */
  22. #include <chrono>
  23. #include <map>
  24. #include <opencv2/videoio.hpp>
  25. #include <opencv2/gapi/garg.hpp>
  26. #include <opencv2/gapi/streaming/meta.hpp>
  27. namespace cv {
  28. namespace gapi {
  29. namespace wip {
  30. /**
  31. * @brief OpenCV's VideoCapture-based streaming source.
  32. *
  33. * This class implements IStreamSource interface.
  34. * Its constructor takes the same parameters as cv::VideoCapture does.
  35. *
  36. * Please make sure that videoio OpenCV module is available before using
  37. * this in your application (G-API doesn't depend on it directly).
  38. *
  39. * @note stream sources are passed to G-API via shared pointers, so
  40. * please gapi::make_src<> to create objects and ptr() to pass a
  41. * GCaptureSource to cv::gin().
  42. */
  43. class GCaptureSource: public IStreamSource
  44. {
  45. public:
  46. explicit GCaptureSource(int id, const std::map<int, double> &properties = {})
  47. : cap(id) { prep(properties); }
  48. explicit GCaptureSource(const std::string &path,
  49. const std::map<int, double> &properties = {})
  50. : cap(path) { prep(properties); }
  51. void set(int propid, double value) {
  52. cap.set(propid, value);
  53. }
  54. // TODO: Add more constructor overloads to make it
  55. // fully compatible with VideoCapture's interface.
  56. protected:
  57. cv::VideoCapture cap;
  58. cv::Mat first;
  59. bool first_pulled = false;
  60. int64_t counter = 0;
  61. void prep(const std::map<int, double> &properties)
  62. {
  63. for (const auto &it : properties) {
  64. cap.set(it.first, it.second);
  65. }
  66. // Prepare first frame to report its meta to engine
  67. // when needed
  68. GAPI_Assert(first.empty());
  69. cv::Mat tmp;
  70. if (!cap.read(tmp))
  71. {
  72. GAPI_Error("Couldn't grab the very first frame");
  73. }
  74. // NOTE: Some decode/media VideoCapture backends continue
  75. // owning the video buffer under cv::Mat so in order to
  76. // process it safely in a highly concurrent pipeline, clone()
  77. // is the only right way.
  78. first = tmp.clone();
  79. }
  80. virtual bool pull(cv::gapi::wip::Data &data) override
  81. {
  82. if (!first_pulled)
  83. {
  84. GAPI_Assert(!first.empty());
  85. first_pulled = true;
  86. data = first; // no need to clone here since it was cloned already
  87. }
  88. else
  89. {
  90. if (!cap.isOpened()) return false;
  91. cv::Mat frame;
  92. if (!cap.read(frame))
  93. {
  94. // end-of-stream happened
  95. return false;
  96. }
  97. // Same reason to clone as in prep()
  98. data = frame.clone();
  99. }
  100. // Tag data with seq_id/ts
  101. const auto now = std::chrono::system_clock::now();
  102. const auto dur = std::chrono::duration_cast<std::chrono::microseconds>
  103. (now.time_since_epoch());
  104. data.meta[cv::gapi::streaming::meta_tag::timestamp] = int64_t{dur.count()};
  105. data.meta[cv::gapi::streaming::meta_tag::seq_id] = int64_t{counter++};
  106. return true;
  107. }
  108. virtual GMetaArg descr_of() const override
  109. {
  110. GAPI_Assert(!first.empty());
  111. return cv::GMetaArg{cv::descr_of(first)};
  112. }
  113. };
  114. // NB: Overload for using from python
  115. GAPI_EXPORTS_W cv::Ptr<IStreamSource>
  116. inline make_capture_src(const std::string& path,
  117. const std::map<int, double>& properties = {})
  118. {
  119. return make_src<GCaptureSource>(path, properties);
  120. }
  121. // NB: Overload for using from python
  122. GAPI_EXPORTS_W cv::Ptr<IStreamSource>
  123. inline make_capture_src(const int id,
  124. const std::map<int, double>& properties = {})
  125. {
  126. return make_src<GCaptureSource>(id, properties);
  127. }
  128. } // namespace wip
  129. } // namespace gapi
  130. } // namespace cv
  131. #endif // OPENCV_GAPI_STREAMING_CAP_HPP