rmat.hpp
5.95 KB
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
// 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::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<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 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;
virtual void serialize(cv::gapi::s11n::IOStream&) {
GAPI_Assert(false && "Generic serialize method of RMat::Adapter does nothing by default. "
"Please, implement it in derived class to properly serialize the object.");
}
virtual void deserialize(cv::gapi::s11n::IIStream&) {
GAPI_Assert(false && "Generic deserialize method of RMat::Adapter does nothing by default. "
"Please, implement it in derived class to properly deserialize the object.");
}
};
using AdapterP = std::shared_ptr<Adapter>;
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<Adapter, T>::value, "T is not derived from Adapter!");
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 */