1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
// 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 <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/own/exports.hpp>
// Forward declaration
namespace cv {
namespace gapi {
namespace s11n {
struct IOStream;
struct IIStream;
} // namespace s11n
} // namespace gapi
} // namespace cv
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::IAdapter class
//
// The basic flow is the following:
// * Backend which is aware of the remote device:
// - Implements own AdapterT class which is derived from RMat::IAdapter
// - Wraps device memory into RMat via make_rmat utility function:
// cv::RMat rmat = cv::make_rmat<AdapterT>(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
// }
/** \addtogroup gapi_data_structures
* @{
*/
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<void()>;
using stepsT = std::vector<size_t>;
View() = default;
View(const GMatDesc& desc, uchar* data, const stepsT& steps = {}, DestroyCallback&& cb = nullptr);
View(const GMatDesc& desc, uchar* data, size_t step, DestroyCallback&& cb = nullptr);
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<int>& 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;
int depth() const { return m_desc.depth; }
int chan() const { return m_desc.chan; }
size_t elemSize() const { return CV_ELEM_SIZE(type()); }
template<typename T = uchar> T* ptr(int y = 0) {
return reinterpret_cast<T*>(m_data + step()*y);
}
template<typename T = uchar> const T* ptr(int y = 0) const {
return reinterpret_cast<T*>(m_data + step()*y);
}
template<typename T = uchar> T* ptr(int y, int x) {
return reinterpret_cast<T*>(m_data + step()*y + step(1)*x);
}
template<typename T = uchar> const T* ptr(int y, int x) const {
return reinterpret_cast<const T*>(m_data + step()*y + step(1)*x);
}
size_t step(size_t i = 0) const { GAPI_DbgAssert(i<m_steps.size()); return m_steps[i]; }
const stepsT& steps() const { return m_steps; }
private:
GMatDesc m_desc;
uchar* m_data = nullptr;
stepsT m_steps = {0u};
DestroyCallback m_cb = nullptr;
};
enum class Access { R, W };
class IAdapter
// Adapter class is going to be deleted and renamed as IAdapter
{
public:
virtual ~IAdapter() = 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;
virtual void serialize(cv::gapi::s11n::IOStream&) {
GAPI_Error("Generic serialize method of RMat::IAdapter does nothing by default. "
"Please, implement it in derived class to properly serialize the object.");
}
virtual void deserialize(cv::gapi::s11n::IIStream&) {
GAPI_Error("Generic deserialize method of RMat::IAdapter does nothing by default. "
"Please, implement it in derived class to properly deserialize the object.");
}
};
using Adapter = IAdapter; // Keep backward compatibility
using AdapterP = std::shared_ptr<IAdapter>;
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<typename T> T* get() const
{
static_assert(std::is_base_of<IAdapter, T>::value, "T is not derived from IAdapter!");
GAPI_Assert(m_adapter != nullptr);
return dynamic_cast<T*>(m_adapter.get());
}
void serialize(cv::gapi::s11n::IOStream& os) const {
m_adapter->serialize(os);
}
private:
AdapterP m_adapter = nullptr;
};
template<typename T, typename... Ts>
RMat make_rmat(Ts&&... args) { return { std::make_shared<T>(std::forward<Ts>(args)...) }; }
/** @} */
} //namespace cv
#endif /* OPENCV_GAPI_RMAT_HPP */
|