// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // // Copyright (C) 2020 Intel Corporation #ifndef OPENCV_GAPI_RMAT_HPP #define OPENCV_GAPI_RMAT_HPP #include #include namespace cv { // "Remote Mat", a general class which provides an abstraction layer over the data // storage and placement (host, remote device etc) and allows to access this data. // // The device specific implementation is hidden in the RMat::Adapter class // // The basic flow is the following: // * Backend which is aware of the remote device: // - Implements own AdapterT class which is derived from RMat::Adapter // - Wraps device memory into RMat via make_rmat utility function: // cv::RMat rmat = cv::make_rmat(args); // // * End user: // - Writes the code which works with RMats without any knowledge of the remote device: // void func(const cv::RMat& in_rmat, cv::RMat& out_rmat) { // // Fetch input data from the device, get mapped memory for output // cv::RMat::View in_view = in_rmat.access(Access::R); // cv::RMat::View out_view = out_rmat.access(Access::W); // performCalculations(in_view, out_view); // // data from out_view is transferred to the device when out_view is destroyed // } class GAPI_EXPORTS RMat { public: // A lightweight wrapper on image data: // - Doesn't own the memory; // - Doesn't implement copy semantics (it's assumed that a view is created each time // wrapped data is being accessed); // - Has an optional callback which is called when the view is destroyed. class GAPI_EXPORTS View { public: using DestroyCallback = std::function; View() = default; View(const GMatDesc& desc, uchar* data, size_t step = 0u, DestroyCallback&& cb = nullptr) : m_desc(desc), m_data(data), m_step(step == 0u ? elemSize()*cols() : step), m_cb(std::move(cb)) {} View(const View&) = delete; View& operator=(const View&) = delete; View(View&&) = default; View& operator=(View&& v); ~View() { if (m_cb) m_cb(); } cv::Size size() const { return m_desc.size; } const std::vector& dims() const { return m_desc.dims; } int cols() const { return m_desc.size.width; } int rows() const { return m_desc.size.height; } int type() const { return CV_MAKE_TYPE(depth(), chan()); } int depth() const { return m_desc.depth; } int chan() const { return m_desc.chan; } size_t elemSize() const { return CV_ELEM_SIZE(type()); } template T* ptr(int y = 0, int x = 0) { return reinterpret_cast(m_data + m_step*y + x*CV_ELEM_SIZE(type())); } template const T* ptr(int y = 0, int x = 0) const { return reinterpret_cast(m_data + m_step*y + x*CV_ELEM_SIZE(type())); } size_t step() const { return m_step; } private: GMatDesc m_desc; uchar* m_data = nullptr; size_t m_step = 0u; DestroyCallback m_cb = nullptr; }; enum class Access { R, W }; class Adapter { public: virtual ~Adapter() = default; virtual GMatDesc desc() const = 0; // Implementation is responsible for setting the appropriate callback to // the view when accessed for writing, to ensure that the data from the view // is transferred to the device when the view is destroyed virtual View access(Access) = 0; }; using AdapterP = std::shared_ptr; RMat() = default; RMat(AdapterP&& a) : m_adapter(std::move(a)) {} GMatDesc desc() const { return m_adapter->desc(); } // Note: When accessed for write there is no guarantee that returned view // will contain actual snapshot of the mapped device memory // (no guarantee that fetch from a device is performed). The only // guaranty is that when the view is destroyed, its data will be // transferred to the device View access(Access a) const { return m_adapter->access(a); } // Cast underlying RMat adapter to the particular adapter type, // return nullptr if underlying type is different template T* get() const { static_assert(std::is_base_of::value, "T is not derived from Adapter!"); GAPI_Assert(m_adapter != nullptr); return dynamic_cast(m_adapter.get()); } private: AdapterP m_adapter = nullptr; }; template RMat make_rmat(Ts&&... args) { return { std::make_shared(std::forward(args)...) }; } } //namespace cv #endif /* OPENCV_GAPI_RMAT_HPP */