ifw-rtmslib 1.0.0
 
Loading...
Searching...
No Matches
sampleExtInfo.hpp
Go to the documentation of this file.
1
7
8#pragma once
9
10#include <cstdint>
11#include <vector>
12#include <stdexcept>
13#include <cstring>
14#include <boost/endian/conversion.hpp>
15
16#include <ifw/fnd/defs/dataType.hpp>
17
18
19namespace ifw::rtmslib {
20
21 // Full extended-info size: timestamp + datatype + width + height + offset_x + offset_y
22 constexpr std::size_t SIZE_SAMPLE_EXT_INFO = sizeof(double) + 5U * sizeof(std::int32_t);
23
24 namespace {
25 // These defaults must match the in-class initialisers below.
26 constexpr double DEF_TIME_STAMP = 0.0;
27 constexpr int32_t DEF_WIDTH = 0;
28 constexpr int32_t DEF_HEIGHT = 0;
29 constexpr int32_t DEF_OFFSET_X = -1;
30 constexpr int32_t DEF_OFFSET_Y = -1;
31 }
32
34 public:
36 explicit SampleExtInfo(double timestamp);
37 explicit SampleExtInfo(const std::vector<uint8_t>& sample_ext_info);
38
39 ~SampleExtInfo() = default;
40
41 SampleExtInfo& SetTimestamp(double timestamp);
42 double GetTimestamp() const;
43
44 SampleExtInfo& SetDataType(ifw::fnd::datatype::DataType datatype);
45 ifw::fnd::datatype::DataType GetDataType() const;
46
47 SampleExtInfo& SetWidth(std::int32_t width);
48 std::int32_t GetWidth() const;
49
50 SampleExtInfo& SetHeight(std::int32_t height);
51 std::int32_t GetHeight() const;
52
53 SampleExtInfo& SetOffsetX(std::int32_t offset_x);
54 std::int32_t GetOffsetX() const;
55
56 SampleExtInfo& SetOffsetY(std::int32_t offset_y);
57 std::int32_t GetOffsetY() const;
58
77 void Pack(std::vector<uint8_t>& sample_ext_info_packed) const;
78
89 void Unpack(const std::vector<uint8_t>& sample_ext_info_packed);
90
93 int32_t GetExtInfoSize() const;
94
95
96 private:
97 double m_timestamp{DEF_TIME_STAMP};
98 ifw::fnd::datatype::DataType m_datatype{ifw::fnd::datatype::DataType::UNSPECIFIED};
99 std::int32_t m_width{DEF_WIDTH};
100 std::int32_t m_height{DEF_HEIGHT};
101 std::int32_t m_offset_x{DEF_OFFSET_X};
102 std::int32_t m_offset_y{DEF_OFFSET_Y};
103 };
104
105 // ===== Inline implementation ==============================================
106
107 inline SampleExtInfo::SampleExtInfo() = default;
108
109 inline SampleExtInfo::SampleExtInfo(double timestamp) {
110 m_timestamp = timestamp;
111 }
112
114 const std::vector<uint8_t>& sample_ext_info) {
115 Unpack(sample_ext_info);
116 }
117
118 inline SampleExtInfo& SampleExtInfo::SetTimestamp(double timestamp) {
119 m_timestamp = timestamp;
120 return *this;
121 }
122
123 inline double SampleExtInfo::GetTimestamp() const {
124 return m_timestamp;
125 }
126
127 inline SampleExtInfo& SampleExtInfo::SetDataType(ifw::fnd::datatype::DataType datatype) {
128 m_datatype = datatype;
129 return *this;
130 }
131
132 inline ifw::fnd::datatype::DataType SampleExtInfo::GetDataType() const {
133 return m_datatype;
134 }
135
136 inline SampleExtInfo& SampleExtInfo::SetWidth(std::int32_t width) {
137 m_width = width;
138 return *this;
139 }
140
141 inline std::int32_t SampleExtInfo::GetWidth() const {
142 return m_width;
143 }
144
145 inline SampleExtInfo& SampleExtInfo::SetHeight(std::int32_t height) {
146 m_height = height;
147 return *this;
148 }
149
150 inline std::int32_t SampleExtInfo::GetHeight() const {
151 return m_height;
152 }
153
154 inline SampleExtInfo& SampleExtInfo::SetOffsetX(std::int32_t offset_x) {
155 m_offset_x = offset_x;
156 return *this;
157 }
158
159 inline std::int32_t SampleExtInfo::GetOffsetX() const {
160 return m_offset_x;
161 }
162
163 inline SampleExtInfo& SampleExtInfo::SetOffsetY(std::int32_t offset_y) {
164 m_offset_y = offset_y;
165 return *this;
166 }
167
168 inline std::int32_t SampleExtInfo::GetOffsetY() const {
169 return m_offset_y;
170 }
171
172 inline void SampleExtInfo::Pack(std::vector<uint8_t>& sample_ext_info_packed) const {
173 sample_ext_info_packed.clear();
174
175 const bool ts_is_def = (m_timestamp == DEF_TIME_STAMP);
176 const bool dt_is_def = (m_datatype == ifw::fnd::datatype::DataType::UNSPECIFIED);
177 const bool w_is_def = (m_width == DEF_WIDTH);
178 const bool h_is_def = (m_height == DEF_HEIGHT);
179 const bool ox_is_def = (m_offset_x == DEF_OFFSET_X);
180 const bool oy_is_def = (m_offset_y == DEF_OFFSET_Y);
181
182 const bool all_default =
183 ts_is_def && dt_is_def && w_is_def && h_is_def &&
184 ox_is_def && oy_is_def;
185
186 if (all_default) {
187 // Case 1: no values to be packed.
188 return;
189 }
190
191 const bool others_all_default =
192 dt_is_def && w_is_def && h_is_def && ox_is_def && oy_is_def;
193
194 if (!ts_is_def && others_all_default) {
195 // Case 2: only timestamp.
196 sample_ext_info_packed.resize(sizeof(double));
197 unsigned char* char_ptr = reinterpret_cast<unsigned char*>(sample_ext_info_packed.data());
198 uint64_t ts_bits = 0;
199 std::memcpy(&ts_bits, &m_timestamp, sizeof(ts_bits));
200 ts_bits = boost::endian::native_to_big(ts_bits);
201 std::memcpy(char_ptr, &ts_bits, sizeof(ts_bits));
202 return;
203 }
204
205 // Otherwise at least one of the extended fields is non-default.
206 // We only allow the full set together with a non-default timestamp.
207 const bool some_other_non_default =
208 !dt_is_def || !w_is_def || !h_is_def || !ox_is_def || !oy_is_def;
209 const bool all_other_non_default =
210 !dt_is_def && !w_is_def && !h_is_def && !ox_is_def && !oy_is_def;
211
212 if (!(some_other_non_default && all_other_non_default && !ts_is_def)) {
213 throw std::runtime_error(fmt::format("{}: SampleExtInfo::Pack: invalid combination of "
214 "fields; allowed are: none, only timestamp, or "
215 "timestamp + datatype + width + height + offset_x + offset_y.", IFWLOC));
216 }
217
218 // Case 3: full set (timestamp + datatype + width + height + offsets).
219 constexpr std::size_t full_size = SIZE_SAMPLE_EXT_INFO;
220
221 sample_ext_info_packed.resize(full_size);
222 unsigned char* char_ptr = reinterpret_cast<unsigned char*>(sample_ext_info_packed.data());
223 std::size_t idx = 0;
224
225 // Timestamp
226 uint64_t ts_bits = 0;
227 std::memcpy(&ts_bits, &m_timestamp, sizeof(ts_bits));
228 ts_bits = boost::endian::native_to_big(ts_bits);
229 std::memcpy(char_ptr + idx, &ts_bits, sizeof(ts_bits));
230 idx += sizeof(ts_bits);
231
232 // Data type as 32-bit integer
233 std::int32_t dt = static_cast<std::int32_t>(m_datatype);
234 dt = boost::endian::native_to_big(dt);
235 std::memcpy(char_ptr + idx, &dt, sizeof(dt));
236 idx += sizeof(dt);
237
238 // Width
239 auto w_be = boost::endian::native_to_big(m_width);
240 std::memcpy(char_ptr + idx, &w_be, sizeof(w_be));
241 idx += sizeof(m_width);
242
243 // Height
244 auto h_be = boost::endian::native_to_big(m_height);
245 std::memcpy(char_ptr + idx, &h_be, sizeof(h_be));
246 idx += sizeof(m_height);
247
248 // Offset X
249 auto ox_be = boost::endian::native_to_big(m_offset_x);
250 std::memcpy(char_ptr + idx, &ox_be, sizeof(ox_be));
251 idx += sizeof(ox_be);
252
253 // Offset Y
254 auto oy_be = boost::endian::native_to_big(m_offset_y);
255 std::memcpy(char_ptr + idx, &oy_be, sizeof(oy_be));
256 idx += sizeof(oy_be);
257 }
258
259 inline void SampleExtInfo::Unpack(const std::vector<uint8_t>& sample_ext_info_packed) {
260 const std::size_t sz = sample_ext_info_packed.size();
261
262 if (sz == 0U) {
263 // No values: reset to defaults.
264 m_timestamp = DEF_TIME_STAMP;
265 m_datatype = ifw::fnd::datatype::DataType::UNSPECIFIED;
266 m_width = DEF_WIDTH;
267 m_height = DEF_HEIGHT;
268 m_offset_x = DEF_OFFSET_X;
269 m_offset_y = DEF_OFFSET_Y;
270 return;
271 }
272
273 if (sz == sizeof(double)) {
274 // Only timestamp.
275 const unsigned char* char_ptr =
276 reinterpret_cast<const unsigned char*>(
277 sample_ext_info_packed.data());
278 std::size_t idx = 0;
279
280 uint64_t ts_bits = 0;
281 std::memcpy(&ts_bits, char_ptr + idx, sizeof(ts_bits));
282 ts_bits = boost::endian::big_to_native(ts_bits);
283 std::memcpy(&m_timestamp, &ts_bits, sizeof(m_timestamp));
284 idx += sizeof(ts_bits);
285
286 // Others back to defaults.
287 m_datatype = ifw::fnd::datatype::DataType::UNSPECIFIED;
288 m_width = DEF_WIDTH;
289 m_height = DEF_HEIGHT;
290 m_offset_x = DEF_OFFSET_X;
291 m_offset_y = DEF_OFFSET_Y;
292 return;
293 }
294
295 if (sz != SIZE_SAMPLE_EXT_INFO) {
296 throw std::runtime_error(fmt::format("{}: SampleExtInfo::Unpack: invalid packed size; "
297 "expected 0, 8 (timestamp), or full-size (timestamp + datatype + width + height + "
298 "offset_x + offset_y).", IFWLOC));
299 }
300
301 const unsigned char* char_ptr =
302 reinterpret_cast<const unsigned char*>(sample_ext_info_packed.data());
303 std::size_t idx = 0;
304
305 // Timestamp
306 uint64_t ts_bits = 0;
307 std::memcpy(&ts_bits, char_ptr + idx, sizeof(ts_bits));
308 ts_bits = boost::endian::big_to_native(ts_bits);
309 std::memcpy(&m_timestamp, &ts_bits, sizeof(m_timestamp));
310 idx += sizeof(ts_bits);
311
312 // Data type (int32 -> enum)
313 std::int32_t dt_int = 0;
314 std::memcpy(&dt_int, char_ptr + idx, sizeof(dt_int));
315 dt_int = boost::endian::big_to_native(dt_int);
316 idx += sizeof(dt_int);
317 m_datatype = static_cast<ifw::fnd::datatype::DataType>(dt_int);
318
319 // Width
320 std::memcpy(&m_width, char_ptr + idx, sizeof(m_width));
321 m_width = boost::endian::big_to_native(m_width);
322 idx += sizeof(m_width);
323
324 // Height
325 std::memcpy(&m_height, char_ptr + idx, sizeof(m_height));
326 m_height = boost::endian::big_to_native(m_height);
327 idx += sizeof(m_height);
328
329 // Offset X
330 std::memcpy(&m_offset_x, char_ptr + idx, sizeof(m_offset_x));
331 m_offset_x = boost::endian::big_to_native(m_offset_x);
332 idx += sizeof(m_offset_x);
333
334 // Offset Y
335 std::memcpy(&m_offset_y, char_ptr + idx, sizeof(m_offset_y));
336 m_offset_y = boost::endian::big_to_native(m_offset_y);
337 idx += sizeof(m_offset_y);
338 }
339
340 inline int32_t SampleExtInfo::GetExtInfoSize() const {
341 bool has_timestamp = (m_timestamp != DEF_TIME_STAMP);
342 bool has_any_extra =
343 (m_datatype != ifw::fnd::datatype::DataType::UNSPECIFIED) ||
344 (m_width != DEF_WIDTH) ||
345 (m_height != DEF_HEIGHT) ||
346 (m_offset_x != DEF_OFFSET_X) ||
347 (m_offset_y != DEF_OFFSET_Y);
348
349 // Case 1: no extended info
350 if (!has_timestamp && !has_any_extra) {
351 return 0;
352 }
353
354 // Case 2: only timestamp
355 if (has_timestamp && !has_any_extra) {
356 return sizeof(double);
357 }
358
359 // Case 3: full basic image info (timestamp + datatype + w + h + ox + oy)
360 if (has_timestamp && has_any_extra) {
361 return sizeof(double) + static_cast<int32_t>(sizeof(int32_t) * 5);
362 }
363
364 // Any partial combination is invalid
365 throw std::runtime_error(
366 "Invalid SampleExtInfo info provided: partial basic image info not allowed");
367 }
368
369} // namespace ifw::rtmslib
std::int32_t GetOffsetY() const
Definition sampleExtInfo.hpp:168
double GetTimestamp() const
Definition sampleExtInfo.hpp:123
ifw::fnd::datatype::DataType GetDataType() const
Definition sampleExtInfo.hpp:132
std::int32_t GetOffsetX() const
Definition sampleExtInfo.hpp:159
std::int32_t GetWidth() const
Definition sampleExtInfo.hpp:141
int32_t GetExtInfoSize() const
Return size in bytes of the packed Extended Info.
Definition sampleExtInfo.hpp:340
SampleExtInfo & SetOffsetY(std::int32_t offset_y)
Definition sampleExtInfo.hpp:163
SampleExtInfo & SetHeight(std::int32_t height)
Definition sampleExtInfo.hpp:145
std::int32_t GetHeight() const
Definition sampleExtInfo.hpp:150
SampleExtInfo & SetOffsetX(std::int32_t offset_x)
Definition sampleExtInfo.hpp:154
void Pack(std::vector< uint8_t > &sample_ext_info_packed) const
Pack the extended info into a byte vector.
Definition sampleExtInfo.hpp:172
SampleExtInfo & SetDataType(ifw::fnd::datatype::DataType datatype)
Definition sampleExtInfo.hpp:127
SampleExtInfo & SetWidth(std::int32_t width)
Definition sampleExtInfo.hpp:136
SampleExtInfo & SetTimestamp(double timestamp)
Definition sampleExtInfo.hpp:118
void Unpack(const std::vector< uint8_t > &sample_ext_info_packed)
Unpack the extended info from a byte vector.
Definition sampleExtInfo.hpp:259
Common utilities for RTMS Lib.
Definition common.cpp:21
constexpr std::size_t SIZE_SAMPLE_EXT_INFO
Definition sampleExtInfo.hpp:22