Skip to content

Commit 18b8c03

Browse files
refactor(pj_base)!: remove the AssetVideo builtin object type (#131)
AssetVideo is superseded by the lazy PJ.VideoFrame path. The MP4 and LeRobot loaders already produce VideoFrame, and nothing in the SDK, PJ4, or pj-official-plugins (main) produces or consumes AssetVideo anymore. Remove the struct, codec, the PJ.AssetVideo .proto contract, and tests. Drop the kAssetVideo (C++ BuiltinObjectType) and PJ_BUILTIN_OBJECT_TYPE_ASSET_VIDEO (C ABI) enumerators, plus the name()/parseBuiltinObjectType()/typeOf() arms. Slot 12 becomes a permanently-reserved gap, mirroring the existing slot-2 reserve — ids 13..18 keep their values; nothing is renumbered. Anything classified as type-id 12 now degrades to kNone and is rejected (the std::any forward-compat path), never silently reinterpreted. The ABI sentinel test loses its ==12 pin (the symbol is gone); the existing ==11 and ==13 pins bracket the reserved hole, and this also adds the previously-missing VoxelGrid ==18 sentinel. abi/baseline.abi is unchanged (the codec is a static lib, not exported ABI; the enum is header-only — abidiff shows no delta). Docs updated: builtin_type.md, proto/pj/README.md, and both CLAUDE.md files (type/codec counts 17->16 and 16->15; reserved-slot notes now list 2 and 12). BREAKING CHANGE: removes a canonical builtin object schema. Per the SDK versioning contract this warrants a MAJOR (1.0.0) bump. Version sources are intentionally left at 0.10.0 in this commit — the maintainer will cut the version together with the other breaking changes batched for 1.0.0. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent dd126ed commit 18b8c03

14 files changed

Lines changed: 10 additions & 437 deletions

CLAUDE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ two modules below have no own CLAUDE.md.
1515
### Modules
1616

1717
- **pj_base** — vocabulary types (`Timestamp`, `DatasetId`, `Expected<T>`, `Span<T>`, type trees),
18-
the canonical builtin object vocabulary (`pj_base/builtin/`: 17 struct headers — Image, DepthImage,
19-
PointCloud, CompressedPointCloud, OccupancyGrid(+Update), Mesh3D, VideoFrame, AssetVideo,
20-
SceneEntities, RobotDescription, CameraInfo, Log, ImageAnnotations, FrameTransforms, PosesInFrame, VoxelGrid) and their 16
18+
the canonical builtin object vocabulary (`pj_base/builtin/`: 16 struct headers — Image, DepthImage,
19+
PointCloud, CompressedPointCloud, OccupancyGrid(+Update), Mesh3D, VideoFrame,
20+
SceneEntities, RobotDescription, CameraInfo, Log, ImageAnnotations, FrameTransforms, PosesInFrame, VoxelGrid) and their 15
2121
wire codecs (RobotDescription carries source text as-is — no codec), the C-ABI protocol headers for
2222
DataSource/MessageParser/Toolbox + the C++ SDK base classes / host-view helpers built on them.
2323
- **pj_plugins** — host-side loaders + RAII handles + plugin discovery/catalog for four plugin

docs/builtin_type.md

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ The public headers live under:
2222
#include <pj_base/builtin/occupancy_grid.hpp>
2323
#include <pj_base/builtin/mesh3d.hpp>
2424
#include <pj_base/builtin/video_frame.hpp>
25-
#include <pj_base/builtin/asset_video.hpp>
2625
#include <pj_base/builtin/scene_entities.hpp>
2726
#include <pj_base/builtin/robot_description.hpp>
2827
#include <pj_base/builtin/image_annotations.hpp>
@@ -36,7 +35,6 @@ The public headers live under:
3635
#include <pj_base/builtin/occupancy_grid_codec.hpp>
3736
#include <pj_base/builtin/mesh3d_codec.hpp>
3837
#include <pj_base/builtin/video_frame_codec.hpp>
39-
#include <pj_base/builtin/asset_video_codec.hpp>
4038
#include <pj_base/builtin/scene_entities_codec.hpp>
4139
#include <pj_base/builtin/image_annotations_codec.hpp>
4240
#include <pj_base/builtin/frame_transforms_codec.hpp>
@@ -86,7 +84,7 @@ Builtin objects fall into two serialization families:
8684
| Family | Current types | Storage model | Codec policy |
8785
|--------|---------------|---------------|--------------|
8886
| Byte-backed views | `Image`, `DepthImage`, `PointCloud`, `CompressedPointCloud`, `OccupancyGrid`, `OccupancyGridUpdate`, `VoxelGrid`, `Mesh3D`, `VideoFrame` | Header fields live in the SDK struct; payload bytes live behind `Span<const uint8_t>` plus `BufferAnchor`. | No mandatory canonical codec; preserve zero-copy views over ROS, MCAP, compressed image, point-cloud, or plugin-owned payloads. If conversion is unavoidable, allocate a new payload and anchor it. |
89-
| Owned values | `ImageAnnotations`, `FrameTransforms`, `SceneEntities`, `AssetVideo`, `RobotDescription`, `CameraInfo`, `PosesInFrame`; future marker types | SDK structs own their vectors/strings/scalars directly. | Add explicit codecs when canonical bytes are needed. Codecs serialize the owned value to the protobuf-wire payload described by the `.proto` contract, using shared private wire primitives. `RobotDescription` carries source-format text as-is (no canonical codec) — the format hint distinguishes URDF / SDF / MJCF. |
87+
| Owned values | `ImageAnnotations`, `FrameTransforms`, `SceneEntities`, `RobotDescription`, `CameraInfo`, `PosesInFrame`; future marker types | SDK structs own their vectors/strings/scalars directly. | Add explicit codecs when canonical bytes are needed. Codecs serialize the owned value to the protobuf-wire payload described by the `.proto` contract, using shared private wire primitives. `RobotDescription` carries source-format text as-is (no canonical codec) — the format hint distinguishes URDF / SDF / MJCF. |
9088

9189
Canonical `.proto` files live under `pj_base/proto/pj` and act as the wire
9290
format contract. One file per top-level message, each named after its message
@@ -120,7 +118,6 @@ annotations, frame transforms, or no builtin object.
120118
| `kMesh3D` | `PJ::sdk::Mesh3D` | 3D mesh asset in its native binary format (GLTF/GLB/STL/PLY/OBJ/USD/DAE). |
121119
| `kVideoFrame` | `PJ::sdk::VideoFrame` | One frame of an inter-frame-coded video stream (h264/h265/vp9/av1). |
122120
| `kSceneEntities` | `PJ::sdk::SceneEntities` | Procedural 3D scene primitives (arrows, cubes, lines, text, …). |
123-
| `kAssetVideo` | `PJ::sdk::AssetVideo` | File-backed video reference plus typed playback metadata. |
124121
| `kRobotDescription` | `PJ::sdk::RobotDescription` | Raw URDF/SDF/MJCF text + format hint. |
125122
| `kCameraInfo` | `PJ::sdk::CameraInfo` | Pinhole camera calibration (intrinsics K, distortion D, rectification R, projection P). |
126123
| `kOccupancyGridUpdate` | `PJ::sdk::OccupancyGridUpdate` | Incremental sub-rectangle patch for a previously-published `OccupancyGrid`. |
@@ -421,44 +418,6 @@ frames within a stream.
421418
`pj_base/builtin/video_frame_codec.hpp` serializes and deserializes this
422419
type using the canonical `PJ.VideoFrame` protobuf wire format.
423420

424-
## AssetVideo
425-
426-
`AssetVideo` is the entry-point handle for video assets ingested by data
427-
loaders that point at an external media file — LeRobot datasets, MP4
428-
loaders, and similar. Producers push exactly one `AssetVideo` per topic;
429-
the ObjectStore timestamp of that entry equals `time_origin_ns` so
430-
timeline UIs naturally see the asset's start instant.
431-
432-
Unlike `VideoFrame` (a single frame of a streamed payload), `AssetVideo`
433-
carries no pixel data — it references the file by path and surfaces
434-
decode-routing metadata (media type, dimensions, frame rate) without
435-
forcing the consumer to open the file just to size a playback window.
436-
437-
| Field | Type | Notes |
438-
|-------|------|-------|
439-
| `time_origin_ns` | `std::optional<Timestamp>` | Wall-clock instant of the first frame. Absent means the asset is not aligned to wall clock. |
440-
| `start_ns` | `std::optional<int64_t>` | In-file offset (ns) where the playable window begins. Absent means "play from the start of the file". |
441-
| `end_ns` | `std::optional<int64_t>` | In-file offset (ns) where the playable window ends. Absent means "play to the end of the file". |
442-
| `file_path` | `std::string` | Absolute path or path relative to a consumer-known root. |
443-
| `media_type` | `std::string` | MIME type hint. Empty means probe the file. |
444-
| `width` | `uint32_t` | Pixel width. `0` means unknown. |
445-
| `height` | `uint32_t` | Pixel height. `0` means unknown. |
446-
| `frame_rate` | `double` | Nominal FPS. `0` or NaN means unknown. |
447-
448-
When both `start_ns` and `end_ns` are absent the whole file is the playable
449-
window. When present, consumers must clamp seek requests to
450-
`[start_ns, end_ns]` and bound timeline UI to that range. This is how
451-
producers expose one clip out of a file that holds many concatenated
452-
clips — for example LeRobot v3.0, where a single MP4 per camera packs
453-
many episodes back-to-back and `[from_timestamp, to_timestamp]` in the
454-
episode metadata maps directly to `[start_ns, end_ns]`.
455-
456-
The total file duration is *not* carried in the message — the decoder
457-
backend reports it.
458-
459-
`pj_base/builtin/asset_video_codec.hpp` serializes and deserializes this
460-
type using the canonical `PJ.AssetVideo` protobuf wire format.
461-
462421
## SceneEntities
463422

464423
`SceneEntities` is the workhorse for marker-style 3D visualization — the
@@ -640,7 +599,6 @@ using the canonical `PJ.VoxelGrid` protobuf wire format.
640599
| URDF / `visualization_msgs/Marker` mesh resource | `Mesh3D` | Embed `data` (with `format`) or point at `url`; preserve `pose` and `scale`. |
641600
| ROS `nav_msgs/Path`, marker arrays | `SceneEntities` | Map polylines to `LinePrimitive`, arrows to `ArrowPrimitive`, etc. |
642601
| H.264/H.265/VP9/AV1 stream frame | `VideoFrame` | Forward one frame's bitstream bytes plus the codec identifier. |
643-
| MP4 / MKV / AV1 dataset file | `AssetVideo` | Push once per topic with the file path and metadata; consumers seek into the file by tracker time. |
644602
| Detection or tracking message | `ImageAnnotations` | Convert boxes, points, circles, and labels into pixel-space primitives. |
645603
| ROS `tf2_msgs/TFMessage` | `FrameTransforms` | Convert transform batches into named parent/child frame relationships. |
646604
| ROS `geometry_msgs/PoseArray` | `PosesInFrame` | Forward timestamp, frame, and the pose array; the viewer chooses how to draw them. |

pj_base/CLAUDE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
# pj_base — SDK vocabulary, builtin object schemas, and the C plugin ABI
22

3-
pj_base is the **Level 0** foundation and the **SDK boundary** for plugin authors. It owns: the zero-dependency vocabulary types (`Timestamp`, `DatasetId`, `Range`, `Expected<T>`, `Span`, `TypeTree`); the canonical *builtin object* schemas (`sdk::Image`, `PointCloud`, `DepthImage`, `OccupancyGrid`, `VoxelGrid`, `FrameTransforms`, … — 17 types) **and 16 of their wire codecs** (RobotDescription has none); and the **C ABI** primitives every plugin family speaks (`plugin_data_api.h` + the service registry) plus the C-ABI protocol headers for **three** families — `data_source_protocol.h`, `message_parser_protocol.h`, `toolbox_protocol.h`. The **Dialog** protocol header is the exception: it lives in `pj_plugins/dialog_protocol/`, not here. It also ships the C++ SDK base classes for DataSource and Toolbox; the MessageParser and Dialog base classes live in `pj_plugins`. Builds as a STATIC lib with **zero public deps** — `fast_float` is a `BUILD_INTERFACE` private impl detail of `parseNumber`. Must NOT depend on `pj_datastore`, `pj_plugins`, Qt, or any Conan runtime lib. This is a read-only submodule subtree: change it only when explicitly working in `plotjuggler_sdk`.
3+
pj_base is the **Level 0** foundation and the **SDK boundary** for plugin authors. It owns: the zero-dependency vocabulary types (`Timestamp`, `DatasetId`, `Range`, `Expected<T>`, `Span`, `TypeTree`); the canonical *builtin object* schemas (`sdk::Image`, `PointCloud`, `DepthImage`, `OccupancyGrid`, `VoxelGrid`, `FrameTransforms`, … — 16 types) **and 15 of their wire codecs** (RobotDescription has none); and the **C ABI** primitives every plugin family speaks (`plugin_data_api.h` + the service registry) plus the C-ABI protocol headers for **three** families — `data_source_protocol.h`, `message_parser_protocol.h`, `toolbox_protocol.h`. The **Dialog** protocol header is the exception: it lives in `pj_plugins/dialog_protocol/`, not here. It also ships the C++ SDK base classes for DataSource and Toolbox; the MessageParser and Dialog base classes live in `pj_plugins`. Builds as a STATIC lib with **zero public deps** — `fast_float` is a `BUILD_INTERFACE` private impl detail of `parseNumber`. Must NOT depend on `pj_datastore`, `pj_plugins`, Qt, or any Conan runtime lib. This is a read-only submodule subtree: change it only when explicitly working in `plotjuggler_sdk`.
44

55
## Layout
66
- `include/pj_base/` — vocabulary primitives: `types.hpp`, `time.hpp` (absolute time spine: `Timepoint`/`Duration` + `fromRaw`/`toRaw`), `type_tree.hpp`, `dataset.hpp`, `expected.hpp`, `span.hpp`, `number_parse.hpp`, `assert.hpp`, `diagnostic_sink.hpp`, `buffer_anchor.hpp`.
7-
- `include/pj_base/builtin/` — the 17 builtin object struct headers (`*.hpp`; 18 enum values in `BuiltinObjectType`, value 2 reserved) + their 16 wire codecs (`*_codec.hpp`; RobotDescription has none) + the `BuiltinObject` (`std::any`) type-erased holder.
7+
- `include/pj_base/builtin/` — the 16 builtin object struct headers (`*.hpp`; 17 enum values in `BuiltinObjectType`, values 2 and 12 reserved) + their 15 wire codecs (`*_codec.hpp`; RobotDescription has none) + the `BuiltinObject` (`std::any`) type-erased holder.
88
- `include/pj_base/sdk/` — C++ SDK over the ABI: DataSource + Toolbox `*_plugin_base.hpp`, `service_registry.hpp`/`service_traits.hpp`, host views, Arrow RAII holders, `testing/`.
99
- `include/pj_base/*_protocol.h`, `plugin_data_api.h`, `builtin_object_abi.h`, `plugin_abi_export.hpp` — the stable C-ABI surface for DataSource/MessageParser/Toolbox (the Dialog protocol header lives in `pj_plugins/dialog_protocol/`).
1010
- `proto/pj/` — canonical `.proto` wire contracts for the builtin types (see its README).
1111
- `src/`, `tests/` — codec/parse impls and gtests.
1212
- `abi/baseline.abi` — golden libabigail dump; the ABI-stability regression baseline.
1313

1414
## Gotchas
15-
- ABI numbering is **frozen**: `BuiltinObjectType` (builtin_object.hpp) and `PJ_builtin_object_type_t` (builtin_object_abi.h) share stable numeric values — never renumber; type 2 is permanently reserved. Append-only.
15+
- ABI numbering is **frozen**: `BuiltinObjectType` (builtin_object.hpp) and `PJ_builtin_object_type_t` (builtin_object_abi.h) share stable numeric values — never renumber; types 2 and 12 are permanently reserved. Append-only.
1616
- Every vtable slot is `PJ_NOEXCEPT`; a throw across the ABI boundary calls `std::terminate`. See the header block in `plugin_data_api.h`.
1717
- `BuiltinObject` is `std::any`, deliberately not `std::variant`, for forward-compat — recover via `std::any_cast<T>` / `sdk::typeOf`. See `builtin/builtin_object.hpp`.
1818
- ABI/struct-layout or signature changes require a Conan **MINOR** bump and a refreshed `abi/baseline.abi`; tail-appended slots are a PATCH (see submodule CLAUDE.md → Release Versioning).

pj_base/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
# ---------------------------------------------------------------------------
44

55
add_library(pj_base STATIC
6-
src/builtin/asset_video_codec.cpp
76
src/builtin/camera_info_codec.cpp
87
src/builtin/compressed_point_cloud_codec.cpp
98
src/builtin/depth_image_codec.cpp
@@ -103,7 +102,6 @@ if(PJ_BUILD_TESTS)
103102
tests/mesh3d_codec_test.cpp
104103
tests/video_frame_codec_test.cpp
105104
tests/scene_entities_codec_test.cpp
106-
tests/asset_video_codec_test.cpp
107105
tests/time_spine_test.cpp
108106
tests/poses_in_frame_codec_test.cpp
109107
tests/voxel_grid_codec_test.cpp

pj_base/include/pj_base/builtin/asset_video.hpp

Lines changed: 0 additions & 66 deletions
This file was deleted.

pj_base/include/pj_base/builtin/asset_video_codec.hpp

Lines changed: 0 additions & 24 deletions
This file was deleted.

pj_base/include/pj_base/builtin/builtin_object.hpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include <optional>
2727
#include <string_view>
2828

29-
#include "pj_base/builtin/asset_video.hpp"
3029
#include "pj_base/builtin/camera_info.hpp"
3130
#include "pj_base/builtin/compressed_point_cloud.hpp"
3231
#include "pj_base/builtin/depth_image.hpp"
@@ -59,7 +58,7 @@ enum class BuiltinObjectType : uint16_t {
5958
kMesh3D = 9, ///< sdk::Mesh3D — binary mesh asset (GLTF/STL/PLY/OBJ/USD/DAE).
6059
kVideoFrame = 10, ///< sdk::VideoFrame — single frame of h264/h265/vp9/av1 stream.
6160
kSceneEntities = 11, ///< sdk::SceneEntities — procedural 3D scene primitives.
62-
kAssetVideo = 12, ///< sdk::AssetVideo — file-backed video reference + playback metadata.
61+
// 12 reserved — was kAssetVideo (removed; video unified on kVideoFrame). Never reuse.
6362
kRobotDescription = 13, ///< sdk::RobotDescription — raw URDF/SDF/MJCF text + format hint.
6463
kCameraInfo = 14, ///< sdk::CameraInfo — pinhole camera calibration (K/D/R/P).
6564
kOccupancyGridUpdate = 15, ///< sdk::OccupancyGridUpdate — incremental sub-rectangle patch for an OccupancyGrid.
@@ -100,8 +99,6 @@ struct SchemaClassification {
10099
return "kVideoFrame";
101100
case BuiltinObjectType::kSceneEntities:
102101
return "kSceneEntities";
103-
case BuiltinObjectType::kAssetVideo:
104-
return "kAssetVideo";
105102
case BuiltinObjectType::kRobotDescription:
106103
return "kRobotDescription";
107104
case BuiltinObjectType::kCameraInfo:
@@ -154,9 +151,6 @@ struct SchemaClassification {
154151
if (s == "kSceneEntities") {
155152
return BuiltinObjectType::kSceneEntities;
156153
}
157-
if (s == "kAssetVideo") {
158-
return BuiltinObjectType::kAssetVideo;
159-
}
160154
if (s == "kRobotDescription") {
161155
return BuiltinObjectType::kRobotDescription;
162156
}
@@ -218,9 +212,6 @@ using BuiltinObject = std::any;
218212
if (t == typeid(SceneEntities)) {
219213
return BuiltinObjectType::kSceneEntities;
220214
}
221-
if (t == typeid(AssetVideo)) {
222-
return BuiltinObjectType::kAssetVideo;
223-
}
224215
if (t == typeid(RobotDescription)) {
225216
return BuiltinObjectType::kRobotDescription;
226217
}

pj_base/include/pj_base/builtin_object_abi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ typedef enum PJ_builtin_object_type_t {
5151
PJ_BUILTIN_OBJECT_TYPE_MESH3D = 9,
5252
PJ_BUILTIN_OBJECT_TYPE_VIDEO_FRAME = 10,
5353
PJ_BUILTIN_OBJECT_TYPE_SCENE_ENTITIES = 11,
54-
PJ_BUILTIN_OBJECT_TYPE_ASSET_VIDEO = 12,
54+
/* 12 reserved — was PJ_BUILTIN_OBJECT_TYPE_ASSET_VIDEO (removed; video unified on VIDEO_FRAME). */
5555
PJ_BUILTIN_OBJECT_TYPE_ROBOT_DESCRIPTION = 13,
5656
PJ_BUILTIN_OBJECT_TYPE_CAMERA_INFO = 14,
5757
PJ_BUILTIN_OBJECT_TYPE_OCCUPANCY_GRID_UPDATE = 15,

0 commit comments

Comments
 (0)