37 explicit SampleExtInfo(
const std::vector<uint8_t>& sample_ext_info);
77 void Pack(std::vector<uint8_t>& sample_ext_info_packed)
const;
89 void Unpack(
const std::vector<uint8_t>& sample_ext_info_packed);
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};
173 sample_ext_info_packed.clear();
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);
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;
191 const bool others_all_default =
192 dt_is_def && w_is_def && h_is_def && ox_is_def && oy_is_def;
194 if (!ts_is_def && others_all_default) {
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));
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;
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));
221 sample_ext_info_packed.resize(full_size);
222 unsigned char* char_ptr =
reinterpret_cast<unsigned char*
>(sample_ext_info_packed.data());
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);
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));
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);
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);
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);
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);
260 const std::size_t sz = sample_ext_info_packed.size();
264 m_timestamp = DEF_TIME_STAMP;
265 m_datatype = ifw::fnd::datatype::DataType::UNSPECIFIED;
267 m_height = DEF_HEIGHT;
268 m_offset_x = DEF_OFFSET_X;
269 m_offset_y = DEF_OFFSET_Y;
273 if (sz ==
sizeof(
double)) {
275 const unsigned char* char_ptr =
276 reinterpret_cast<const unsigned char*
>(
277 sample_ext_info_packed.data());
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);
287 m_datatype = ifw::fnd::datatype::DataType::UNSPECIFIED;
289 m_height = DEF_HEIGHT;
290 m_offset_x = DEF_OFFSET_X;
291 m_offset_y = DEF_OFFSET_Y;
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));
301 const unsigned char* char_ptr =
302 reinterpret_cast<const unsigned char*
>(sample_ext_info_packed.data());
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);
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);
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);
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);
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);
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);
341 bool has_timestamp = (m_timestamp != DEF_TIME_STAMP);
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);
350 if (!has_timestamp && !has_any_extra) {
355 if (has_timestamp && !has_any_extra) {
356 return sizeof(double);
360 if (has_timestamp && has_any_extra) {
361 return sizeof(double) +
static_cast<int32_t
>(
sizeof(int32_t) * 5);
365 throw std::runtime_error(
366 "Invalid SampleExtInfo info provided: partial basic image info not allowed");