Ocean
Loading...
Searching...
No Matches
DataSerializer.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_IO_SERIALIZATION_DATA_SERIALIZER_H
9#define META_OCEAN_IO_SERIALIZATION_DATA_SERIALIZER_H
10
12
14#include "ocean/base/Thread.h"
15
16#include "ocean/io/Bitstream.h"
19
20namespace Ocean
21{
22
23namespace IO
24{
25
26namespace Serialization
27{
28
29/**
30 * This class implements the base class for data serializers.
31 * Data serializers are used to serialize and deserialize data samples across multiple channels.<br>
32 * Each channel can have a different sample type, name, and content type, allowing heterogeneous data to be organized and streamed together.<br>
33 * The class provides a thread-based architecture where the actual serialization/deserialization happens asynchronously in a background thread.<br>
34 * Derived classes (InputDataSerializer and OutputDataSerializer) implement the specific read or write functionality.
35 * @ingroup ioserialization
36 */
37class OCEAN_IO_SERIALIZATION_EXPORT DataSerializer : protected Thread
38{
39 public:
40
41 /// Definition of a channel id.
42 using ChannelId = uint32_t;
43
44 /**
45 * Returns an invalid channel id.
46 * @return The invalid channel id
47 */
48 static constexpr ChannelId invalidChannelId();
49
50 /**
51 * This class holds channel configuration (sample type, name, and content type).
52 * A channel configuration uniquely identifies the type and purpose of a data channel without including the runtime channel id.<br>
53 * The sample type describes the class type of data samples (e.g., "DataSampleFrame"), the name provides a user-friendly identifier (e.g., "camera_left"), and the content type describes the semantic meaning of the data (e.g., "RGB_FRAME").
54 */
56 {
57 public:
58
59 /**
60 * Definition of a hash function for ChannelConfiguration objects.
61 */
62 struct Hash
63 {
64 /**
65 * Calculates the hash value for a given channel configuration.
66 * @param channelConfiguration The channel configuration for which the hash will be calculated
67 * @return The hash value
68 */
69 inline size_t operator()(const ChannelConfiguration& channelConfiguration) const;
70 };
71
72 public:
73
74 /**
75 * Creates a new invalid channel configuration.
76 */
78
79 /**
80 * Creates a new channel configuration with given sample type, name, and content type.
81 * @param sampleType The sample type
82 * @param name The name of the channel
83 * @param contentType The content type
84 */
85 inline ChannelConfiguration(const std::string& sampleType, const std::string& name, const std::string& contentType);
86
87 /**
88 * Returns the sample type.
89 * @return The sample type
90 */
91 inline const std::string& sampleType() const;
92
93 /**
94 * Returns the name of the channel.
95 * @return The channel name
96 */
97 inline const std::string& name() const;
98
99 /**
100 * Returns the content type.
101 * @return The content type
102 */
103 inline const std::string& contentType() const;
104
105 /**
106 * Returns whether this channel configuration is valid.
107 * @return True, if all fields (sample type, name, and content type) are non-empty
108 */
109 inline bool isValid() const;
110
111 /**
112 * Returns whether two channel configurations are equal.
113 * @param channelConfiguration The second channel configuration to compare
114 * @return True, if both configurations are equal
115 */
116 inline bool operator==(const ChannelConfiguration& channelConfiguration) const;
117
118 protected:
119
120 /// The sample type.
121 std::string sampleType_;
122
123 /// The name of the channel.
124 std::string name_;
125
126 /// The content type.
127 std::string contentType_;
128 };
129
130 /**
131 * This class implements a channel with configuration and channel id.
132 * A channel extends ChannelConfiguration by adding a unique channel id that is assigned at runtime during serialization.<br>
133 * The channel id is used to efficiently identify and route data samples within the serialization stream.
134 */
135 class OCEAN_IO_SERIALIZATION_EXPORT Channel : public ChannelConfiguration
136 {
137 public:
138
139 /**
140 * Definition of a hash function for Channel objects.
141 */
142 struct Hash
143 {
144 /**
145 * Calculates the hash value for a given channel.
146 * @param channel The channel for which the hash will be calculated
147 * @return The hash value
148 */
149 inline size_t operator()(const Channel& channel) const;
150 };
151
152 public:
153
154 /**
155 * Creates a new invalid channel.
156 */
157 Channel() = default;
158
159 /**
160 * Creates a new channel with given configuration and channel id.
161 * @param channelConfiguration The channel configuration
162 * @param channelId The channel id
163 */
164 inline Channel(const ChannelConfiguration& channelConfiguration, const ChannelId channelId);
165
166 /**
167 * Returns the channel id.
168 * @return The channel id
169 */
170 inline ChannelId channelId() const;
171
172 /**
173 * Returns whether this channel is valid.
174 * @return True, if the channel id is valid and the configuration is valid
175 */
176 inline bool isValid() const;
177
178 /**
179 * Returns whether two channels are equal.
180 * @param channel The second channel to compare
181 * @return True, if both channels are equal
182 */
183 inline bool operator==(const Channel& channel) const;
184
185 protected:
186
187 /// The channel id.
188 ChannelId channelId_ = invalidChannelId();
189 };
190
191 /// Definition of a vector holding channels.
192 using Channels = std::vector<Channel>;
193
194 protected:
195
196 /**
197 * Definition of individual states the serializer can have.
198 */
199 enum State
200 {
201 /// The serializer has not yet been initialized or started.
203 /// The serializer has been initialized and is ready to start.
205 /// The serializer has been started and is currently actively processing data samples.
207 /// The serializer is currently stopping but may still process remaining data samples.
209 /// The serializer has been stopped and all active processing of data samples has finished. However, there may still be samples left which could be requested by the user.
210 S_STOPPED
211 };
212
213 /// Definition of a map mapping channel configurations to channel ids.
214 using ChannelConfigurationMap = std::unordered_map<ChannelConfiguration, ChannelId, ChannelConfiguration::Hash>;
215
216 /// Definition of a pair holding a channel id and a unique data sample.
217 using SamplePair = std::pair<ChannelId, UniqueDataSample>;
218
219 /**
220 * This class implements a data sample holding channel configuration information.
221 * This internal class is used to serialize channel configuration as a special sample type, allowing the configuration to be embedded in the data stream alongside regular samples.<br>
222 * When a new channel is encountered during playback, the configuration sample is read first to establish the channel's metadata.
223 */
225 public DataSample,
227 {
228 public:
229
230 /**
231 * Creates a new invalid data sample channel configuration.
232 */
234
235 /**
236 * Creates a new data sample channel configuration from a data sample and channel configuration.
237 * @param sample The data sample
238 * @param channelConfiguration The channel configuration
239 */
240 inline explicit DataSampleChannelConfiguration(const DataSample& sample, const ChannelConfiguration& channelConfiguration);
241
242 /**
243 * Creates a new data sample channel configuration from a data timestamp and channel configuration.
244 * @param dataTimestamp The data timestamp
245 * @param channelConfiguration The channel configuration
246 * @param sampleCreationTimestamp The timestamp when the sample was created, this timestamp is not serialized and is only used to automatically determine the playback timestamp
247 */
248 inline explicit DataSampleChannelConfiguration(const DataTimestamp& dataTimestamp, const ChannelConfiguration& channelConfiguration, const Timestamp sampleCreationTimestamp = Timestamp(true));
249
250 /**
251 * Reads the sample from an input bitstream.
252 * @param inputBitstream The input bitstream from which the sample will be read
253 * @return True, if succeeded
254 */
255 inline bool readSample(InputBitstream& inputBitstream) override;
256
257 /**
258 * Writes the sample to an output bitstream.
259 * @param outputBitstream The output bitstream to which the sample will be written
260 * @return True, if succeeded
261 */
262 inline bool writeSample(OutputBitstream& outputBitstream) const override;
263
264 /**
265 * Returns the type of the sample.
266 * @return The sample type
267 */
268 inline const std::string& type() const override;
269 };
270
271 public:
272
273 /**
274 * Destructs the data serializer.
275 */
276 virtual ~DataSerializer() = default;
277
278 /**
279 * Starts the serializer.
280 * @return True, if succeeded
281 */
282 virtual bool start() = 0;
283
284 /**
285 * Stops the serializer.
286 * This function sets a stopping flag and returns immediately; it does not wait for the serializer to actually stop.
287 * The background thread will check the stopping flag and terminate asynchronously.
288 * Use stopAndWait() to wait until the serializer has fully stopped, or poll hasStopped() to check if it has stopped.
289 * @return True, if the stop request was accepted; False, if the serializer was not started
290 * @see stopAndWait(), hasStopped().
291 */
292 virtual bool stop() = 0;
293
294 /**
295 * Stops the serializer and waits until the serializer has stopped.
296 * @param timeout The timeout in seconds, with range (0, infinity)
297 * @return True, if the serializer stopped within the given timeout
298 */
299 virtual bool stopAndWait(const double timeout = 60.0);
300
301 /**
302 * Returns whether the serializer has been started.
303 * @return True, if so
304 */
305 [[nodiscard]] virtual bool isStarted() const = 0;
306
307 /**
308 * Returns whether the serializer has stopped but does not check wehther remaining samples have not yet been processed or retrieved.
309 * @return True, if so
310 */
311 [[nodiscard]] virtual bool hasStopped() const;
312
313 /**
314 * Returns whether the serializer has stopped and all remaining samples have been processed or retrieved.
315 * @return True, if so
316 * @see DataSerializer::hasFinished().
317 */
318 [[nodiscard]] virtual bool hasFinished() const = 0;
319
320 protected:
321
322 /**
323 * Returns whether the given channel value has the configuration bit set.
324 * @param channelValue The channel value to check
325 * @return True, if the channel value is a configuration channel id
326 */
327 [[nodiscard]] static constexpr bool isConfigurationChannelId(const uint32_t channelValue);
328
329 /**
330 * Creates a configuration channel id from a regular channel id by setting the highest bit.
331 * @param channelId The channel id
332 * @return The configuration channel id
333 */
334 [[nodiscard]] static constexpr uint32_t makeConfigurationChannelId(const ChannelId channelId);
335
336 /**
337 * Extracts the channel id from a channel value by clearing the configuration bit.
338 * @param channelValue The channel value
339 * @return The channel id
340 */
341 [[nodiscard]] static constexpr ChannelId extractChannelId(const uint32_t channelValue);
342
343 protected:
344
345 /// The timestamp when the serializer was started.
347
348 /// The current state of the serializer.
349 State state_ = S_IDLE;
350
351 /// True, if the serializer succeeded; False, if an error occurred.
352 bool succeeded_ = true;
353
354 /// The lock for thread-safe access.
355 mutable Lock lock_;
356};
357
362
364{
365 size_t seed = std::hash<std::string>()(channelConfiguration.sampleType_);
366 seed ^= std::hash<std::string>{}(channelConfiguration.name_) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
367 seed ^= std::hash<std::string>{}(channelConfiguration.contentType_) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
368
369 return seed;
370}
371
372inline DataSerializer::ChannelConfiguration::ChannelConfiguration(const std::string& sampleType, const std::string& name, const std::string& contentType) :
374 name_(name),
376{
377 // nothing to do here
378}
379
381{
382 return sampleType_;
383}
384
385inline const std::string& DataSerializer::ChannelConfiguration::name() const
386{
387 return name_;
388}
389
391{
392 return contentType_;
393}
394
396{
397 return !sampleType_.empty() && !name_.empty() && !contentType_.empty();
398}
399
400inline bool DataSerializer::ChannelConfiguration::operator==(const ChannelConfiguration& channelConfiguration) const
401{
402 return sampleType_ == channelConfiguration.sampleType_ && name_ == channelConfiguration.name_ && contentType_ == channelConfiguration.contentType_;
403}
404
405inline size_t DataSerializer::Channel::Hash::operator()(const Channel& channel) const
406{
407 size_t seed = std::hash<uint32_t>()(channel.channelId_);
408 seed ^= ChannelConfiguration::Hash{}(channel) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
409
410 return seed;
411}
412
413inline DataSerializer::Channel::Channel(const ChannelConfiguration& channelConfiguration, const ChannelId channelId) :
414 ChannelConfiguration(channelConfiguration),
415 channelId_(channelId)
416{
417 // nothing to do here
418}
419
421{
422 return channelId_;
423}
424
426{
427 return channelId_ != invalidChannelId() && ChannelConfiguration::isValid();
428}
429
430inline bool DataSerializer::Channel::operator==(const Channel& channel) const
431{
432 return channelId_ == channel.channelId_ && ChannelConfiguration::operator==(channel);
433}
434
435constexpr bool DataSerializer::isConfigurationChannelId(const uint32_t channelValue)
436{
437 constexpr uint32_t highestBit = 1u << 31u;
438
439 return channelValue & highestBit;
440}
441
442constexpr uint32_t DataSerializer::makeConfigurationChannelId(const ChannelId channelId)
443{
444 ocean_assert(channelId != invalidChannelId());
445 ocean_assert(!isConfigurationChannelId(channelId));
446
447 constexpr uint32_t highestBit = 1u << 31u;
448
449 return channelId | highestBit;
450}
451
453{
454 constexpr uint32_t highestBit = 1u << 31u;
455
456 return ChannelId(channelValue & ~highestBit);
457}
458
460 DataSample(sample),
461 ChannelConfiguration(channelConfiguration)
462{
463 // nothing to do here
464}
465
466inline DataSerializer::DataSampleChannelConfiguration::DataSampleChannelConfiguration(const DataTimestamp& dataTimestamp, const ChannelConfiguration& channelConfiguration, const Timestamp sampleCreationTimestamp) :
467 DataSample(dataTimestamp, sampleCreationTimestamp),
468 ChannelConfiguration(channelConfiguration)
469{
470 // nothing to do here
471}
472
474{
475 if (!DataSample::readSample(inputBitstream))
476 {
477 return false;
478 }
479
480 return inputBitstream.read<std::string>(sampleType_) && inputBitstream.read<std::string>(name_) && inputBitstream.read<std::string>(contentType_);
481}
482
484{
485 if (!DataSample::writeSample(outputBitstream))
486 {
487 return false;
488 }
489
490 return outputBitstream.write<std::string>(sampleType_) && outputBitstream.write<std::string>(name_) && outputBitstream.write<std::string>(contentType_);
491}
492
494{
495 return sampleType_;
496}
497
498}
499
500}
501
502}
503
504#endif // META_OCEAN_IO_SERIALIZATION_DATA_SERIALIZER_H
This class implements an input bitstream.
Definition Bitstream.h:51
bool read(T &value)
Reads a value from the bitstream and moves the internal position inside the bitstream accordingly.
This class implements an output bitstream.
Definition Bitstream.h:215
bool write(const T &value)
Writes a data object to the stream and moves the internal position inside the bitstream accordingly.
This class implements a base class for data samples.
Definition DataSample.h:50
virtual bool readSample(InputBitstream &inputBitstream)
Reads the sample from an input bitstream.
virtual bool writeSample(OutputBitstream &outputBitstream) const
Writes the sample to an output bitstream.
This class holds channel configuration (sample type, name, and content type).
Definition DataSerializer.h:56
bool operator==(const ChannelConfiguration &channelConfiguration) const
Returns whether two channel configurations are equal.
Definition DataSerializer.h:400
std::string name_
The name of the channel.
Definition DataSerializer.h:124
std::string contentType_
The content type.
Definition DataSerializer.h:127
ChannelConfiguration()=default
Creates a new invalid channel configuration.
bool isValid() const
Returns whether this channel configuration is valid.
Definition DataSerializer.h:395
const std::string & sampleType() const
Returns the sample type.
Definition DataSerializer.h:380
const std::string & contentType() const
Returns the content type.
Definition DataSerializer.h:390
const std::string & name() const
Returns the name of the channel.
Definition DataSerializer.h:385
std::string sampleType_
The sample type.
Definition DataSerializer.h:121
This class implements a channel with configuration and channel id.
Definition DataSerializer.h:136
Channel()=default
Creates a new invalid channel.
bool operator==(const Channel &channel) const
Returns whether two channels are equal.
Definition DataSerializer.h:430
ChannelId channelId() const
Returns the channel id.
Definition DataSerializer.h:420
bool isValid() const
Returns whether this channel is valid.
Definition DataSerializer.h:425
ChannelId channelId_
The channel id.
Definition DataSerializer.h:188
This class implements a data sample holding channel configuration information.
Definition DataSerializer.h:227
bool readSample(InputBitstream &inputBitstream) override
Reads the sample from an input bitstream.
Definition DataSerializer.h:473
DataSampleChannelConfiguration()=default
Creates a new invalid data sample channel configuration.
bool writeSample(OutputBitstream &outputBitstream) const override
Writes the sample to an output bitstream.
Definition DataSerializer.h:483
const std::string & type() const override
Returns the type of the sample.
Definition DataSerializer.h:493
This class implements the base class for data serializers.
Definition DataSerializer.h:38
static constexpr uint32_t makeConfigurationChannelId(const ChannelId channelId)
Creates a configuration channel id from a regular channel id by setting the highest bit.
Definition DataSerializer.h:442
static constexpr ChannelId invalidChannelId()
Returns an invalid channel id.
Definition DataSerializer.h:358
std::unordered_map< ChannelConfiguration, ChannelId, ChannelConfiguration::Hash > ChannelConfigurationMap
Definition of a map mapping channel configurations to channel ids.
Definition DataSerializer.h:214
Timestamp startTimestamp_
The timestamp when the serializer was started.
Definition DataSerializer.h:346
virtual bool hasStopped() const
Returns whether the serializer has stopped but does not check wehther remaining samples have not yet ...
std::pair< ChannelId, UniqueDataSample > SamplePair
Definition of a pair holding a channel id and a unique data sample.
Definition DataSerializer.h:217
std::vector< Channel > Channels
Definition of a vector holding channels.
Definition DataSerializer.h:192
Lock lock_
The lock for thread-safe access.
Definition DataSerializer.h:355
static constexpr bool isConfigurationChannelId(const uint32_t channelValue)
Returns whether the given channel value has the configuration bit set.
Definition DataSerializer.h:435
virtual bool start()=0
Starts the serializer.
virtual bool stop()=0
Stops the serializer.
virtual bool isStarted() const =0
Returns whether the serializer has been started.
uint32_t ChannelId
Definition of a channel id.
Definition DataSerializer.h:42
virtual bool stopAndWait(const double timeout=60.0)
Stops the serializer and waits until the serializer has stopped.
State
Definition of individual states the serializer can have.
Definition DataSerializer.h:200
@ S_IDLE
The serializer has not yet been initialized or started.
Definition DataSerializer.h:202
@ S_INITIALIZED
The serializer has been initialized and is ready to start.
Definition DataSerializer.h:204
@ S_STARTED
The serializer has been started and is currently actively processing data samples.
Definition DataSerializer.h:206
@ S_STOPPING
The serializer is currently stopping but may still process remaining data samples.
Definition DataSerializer.h:208
virtual ~DataSerializer()=default
Destructs the data serializer.
virtual bool hasFinished() const =0
Returns whether the serializer has stopped and all remaining samples have been processed or retrieved...
static constexpr ChannelId extractChannelId(const uint32_t channelValue)
Extracts the channel id from a channel value by clearing the configuration bit.
Definition DataSerializer.h:452
This class implements a data timestamp which can hold either a double or int64_t value.
Definition DataTimestamp.h:32
This class implements a recursive lock object.
Definition Lock.h:31
This class implements a thread.
Definition Thread.h:115
This class implements a timestamp.
Definition Timestamp.h:64
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
Definition of a hash function for Channel objects.
Definition DataSerializer.h:143
size_t operator()(const Channel &channel) const
Calculates the hash value for a given channel.
Definition DataSerializer.h:405
Definition of a hash function for ChannelConfiguration objects.
Definition DataSerializer.h:63
size_t operator()(const ChannelConfiguration &channelConfiguration) const
Calculates the hash value for a given channel configuration.
Definition DataSerializer.h:363