You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summary:
VRS open source documentation updates.
NOTE: If you want to update this diff, go via the preview link inside the static docs section below.
Ensure you are editing the same page that was used to create this diff.
Differential Revision: D78194609
fbshipit-source-id: 5ace5c715c4b486c8c6b1424f2b39a8b98851b11
Copy file name to clipboardExpand all lines: website/docs/RecordFormat.md
+18-11Lines changed: 18 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,9 +9,9 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
9
9
10
10
Each record in a stream has its own format version number, which is a `uint32_t` value. However, because records belong to a single stream and each has a record type (Configuration, State, or Data), format version numbers are only meaningful within that stream and for that record type. You do not need to worry about format version collisions between streams and record types.
11
11
12
-
Before `RecordFormat` was available, record format versioning was critical, because it was the only information about how the record's data was formatted. You were responsible for interpreting every byte of data. You also had to manually manage all data format changes. Since record data formats were not self-described within the file, each time you needed to add, remove, or change a field, you had to change the format version, and handle a growing number of format versions explicitly in the code. This was unmanageable.
12
+
Before `RecordFormat` was available, record format versioning was critical, because it was the only information about how the record's data was formatted. In the `StreamPlayer` callbacks you received when reading a file, you were responsible for interpreting every byte of data and you also had to manually manage all data format changes. Since record data formats were not self-described within the file, each time you needed to add, remove, or change a field, you had to change the format version, and handle a growing number of format versions explicitly in your code. This was unmanageable. Moreover, it was not possible to write standard tools that could interpret that was stored in records, show the images they might contains, or any other metadata.
13
13
14
-
`RecordFormat` and `DataLayout` were designed to solve this challenge, and since, record format version changes are very rarely needed. `RecordFormat`abstracts the description of a record as a succession of typed blocks, embedding descriptions, including `DataLayout` definitions, in the stream itself. VRS uses these embedded descriptions to interpret records, calculate content block boundaries using DataLayout Conventions, and pass parsed content blocks to callbacks.
14
+
`RecordFormat` and `DataLayout` were designed to solve these challenges, and since, record format version changes are very rarely needed. `RecordFormat`structures records as a succession of typed content blocks, embedding descriptions, including `DataLayout` definitions, in the stream itself. VRS uses these embedded descriptions to interpret records, calculate content block boundaries using DataLayout Conventions, and send parsed content blocks to `RecordFormatStreamPlayer`callbacks when reading a VRS file. With `RecordFormat` and the DataLayout Conventions, it is now possible to write generic tools like vrsplayer, that can let you explore what's in a VRS file without any prior knowledge of the use case in which the file was recorded.
15
15
16
16
## `RecordFormat`
17
17
@@ -23,9 +23,12 @@ The content block types are: `image`, `audio`, `datalayout`, and `custom`. VRS s
23
23
24
24
-`image`
25
25
-`image/png`
26
+
-`image/jpg`
27
+
-`image/jxl`
26
28
-`image/raw`
27
29
-`image/raw/640x480/pixel=grb8`
28
30
-`image/raw/640x480/pixel=grey8/stride=648`
31
+
-`image/custom_codec/codec=my_experiment`
29
32
-`image/video`
30
33
-`image/video/codec=H.264`
31
34
-`audio`
@@ -34,6 +37,7 @@ The content block types are: `image`, `audio`, `datalayout`, and `custom`. VRS s
34
37
-`datalayout`
35
38
-`datalayout/size=48`
36
39
-`custom`
40
+
-`custom/format=my_own_payload_format`
37
41
-`custom/size=160`
38
42
39
43
`image` and `audio` content blocks are pretty much what you expect when you read their text description. `datalayout` blocks contain structured metadata information. `custom` content blocks are blocks of raw data, which format is known only to you, and which you are responsible for interpreting.
@@ -55,9 +59,9 @@ In practice, the majority of the records used in VRS today use one of the follow
55
59
56
60
### Datalayout Content Blocks
57
61
58
-
Datalayout content blocks, commonly referred to as datalayouts, are `DataLayout` objects that hold containers of [POD values](https://en.wikipedia.org/wiki/Passive_data_structure) and strings. If you have never seen a `DataLayout` definition, look at the `MyDataLayout` definition in the **`DataLayout` Examples** section below.
62
+
Datalayout content blocks, commonly referred to as datalayouts, are `DataLayout` objects that hold a collection of `DataPieceXXX` objects, which are containers of [POD values](https://en.wikipedia.org/wiki/Passive_data_structure) and strings. If you have never seen a `DataLayout` definition, look at the `MyDataLayout` definition in the **`DataLayout` Examples** section below.
59
63
60
-
`DataLayout` are `struct` objects containing `DataPieceXXX` member variables, that each have their own text label. The supported `DataPieceXXX` types are:
64
+
`DataLayout` are typically `struct` objects containing a series of `DataPieceXXX` member variables, that each have their own type and text label. The supported `DataPieceXXX` types are:
61
65
62
66
`DataPieceValue`, a single value of POD type `T`:
63
67
@@ -105,7 +109,7 @@ Template class `T` can also be any of these vector types (using `float`, `double
105
109
106
110
<!-- prettier-ignore -->
107
111
:::note
108
-
Always use `<cstdint>` definitions. Never use platform dependent types like `short`, `int`, `long`, or `size_t`. The actual size will vary depending on the architecture or the compiler configuration.
112
+
Always use `<cstdint>` definitions. Never use native platform dependent types like `short`, `int`, `long`, or `size_t`, because their actual size will vary depending on the architecture or the compiler configuration.
109
113
:::
110
114
111
115
### `DataLayout` Format Resilience
@@ -269,7 +273,8 @@ Audio blocks are analog to image blocks, and are handled the same way.
269
273
270
274
```cpp
271
275
ContentBlock(ContentType::CUSTOM); // No details at all
CustomContentBlock("my_thing", 48); // 48 bytes custom content block in the format "my_thing"
273
278
```
274
279
275
280
If they are not the last content block in the record, custom content blocks may need to have their size provided using the Datalayout conventions.
@@ -449,17 +454,19 @@ When reading and writing records, no binary-ascii conversions are made, only bin
449
454
All the power of `DataLayout` lies in its ability to amortize costs. Amortized, `DataLayout` objects...
450
455
451
456
- ...store one byte of payload at the cost of 1 byte of storage (or less, because of record level compression).
452
-
- ...have zero serialization/deserialization overhead, both on read and write, including when handling data version mismatch (that’s when the data stored in a file and the definition you have when reading that file don’t match).
457
+
- ...have zero serialization/deserialization overhead, both on read and write, including when handling a format mismatch (that’s when the data stored in a file and the definition you have when reading that file don’t match).
453
458
- ...have constant field access time, no matter how many you have.
454
459
- ...are pure binary containers (no string conversions, unlike json).
455
460
- ...require no pre-processor/code generation: `DataLayout` definitions are directly compiled by a C++ compiler.
456
461
- ...minimize memory allocations overhead. It’s possible to create and read records without memory allocations beyond record management, even when dealing with variable size arrays (vectors). Again, amortized.
457
462
- ...look, behave, and feel like a simple C++ struct: they are very readable, very easy and efficient to read and write to.
463
+
- ...no format evolution cost: you can iterate over your `DataLayout` definitions as often as you like, they'll be just as efficient as if there had been no format evolutions.
458
464
459
-
The key assumption VRS makes is that data collected within each stream is extremely repetitive throughout a particular file, and everything is done to leverage that property to the fullest. So `DataLayout`stores definitions once per file, parses them once per file-read, maps the `DataLayout`format expected to the `DataLayout` found in the stream once, so all the relatively expensive operations are done only once.
465
+
The key assumption VRS makes is that data collected within each stream is extremely repetitive throughout a particular file, and everything is done to leverage that property to the fullest. `DataLayout` definitions are stored once per stream, parsed once per file-read, expected `DataLayout`formats are mapped to the `DataLayout` found in the stream once, so all the relatively expensive operations are amortized (done only once).
460
466
461
-
### What is `DataLayout` not good at?
467
+
### What is `DataLayout` not so good at?
462
468
463
-
- seamless integration with existing data representations. You will need to write converters to copy your data source(s) to your `DataLayout` definitions, field by field.
469
+
- seamless integration with existing data representations, like structs and other classes. You will need to write converters to copy your data source(s) to your `DataLayout` definitions, field by field.\
470
+
This can feel tedious, but ultimately, protects you against unexpected changes and provides a clear place where to handle format conversions and evolutions.
464
471
- Nested definitions are supported, but with limitations. See [this documentation (in the “Example 2: nested definitions” tab) for details](https://facebookresearch.github.io/vrs/docs/RecordFormat#datalayout-examples). For 99% of sensor data use cases, `DataLayout` works great and this limitation isn’t even apparent, but for advanced use cases with more structured data and variable formats, of when you have nested definitions with variable size data, `DataLayout` conversion becomes a pain point.
465
-
- complex data structures, in particular, arbitrary data structures that might change with every record, or not be known at compile time, so that converter code can not be written. In that case, you might need to use a self-described container, such as json or msgpack (which is a binary version of json). Looking at the needs of sensor data collection, this should be rare, or needed only for configuration records, which is fine, because it’s typically a one record need, and the trade offs are radically different when you need to do an operation once during setup vs. N million times in realtime. For instance, camera calibration is often stored as json in a `DataLayout` of a configuration record, and there is no reason to change that.
472
+
- complex data structures, in particular, arbitrary data structures that might change with every record, or not be known at compile time, so that converter code can not be written. In that case, you might need to use a self-described container, such as json or msgpack (binary variation of json). Looking at the needs of sensor data collection, this should be rare, or needed only for configuration records. Using json in configuration records is fine, because it’s typically a one record need, and the trade offs are radically different when you need to do an expensive operation and store data relatively inneficiently once during setup vs. N million times in realtime (for each record). For instance, camera calibration is often provided as a json string the stream's configuration record, and there is no reason to change that.
0 commit comments