All notable changes to this project are documented here. Format follows Keep a Changelog. Versioning follows Semantic Versioning.
Node architecture
- Modular node split:
src/node/with one file per responsibility (core,lifecycle,modes,streaming,recovery,fallback,observability). Each file stays under 300 lines. - Separate
src/core/(config loading and pipeline building) andsrc/runtime/(capability probe, stream engine, metrics, image format, topic introspector) layers.
Codec & encoder selection
codec.name:=autoresolves the best available codec and encoder usinggst-inspect-1.0output, scored by machine profile (jetson,x86,raspi,generic).- Machine profile auto-detection from host CPU architecture when
profile.machineis left asgeneric. - Hardware-to-software encoder fallback after configurable consecutive failures (
runtime.hw_fallback_failures, default 3).
Transport × codec pipeline matrix
- Full support for
h264,h265,mjpegcodecs acrosssrt,udp,rtsp,filesinks. - Jetson NVMM path for
nvv4l2h264enc/nvv4l2h265enc(CPU → I420 → nvvidconv → NVMM → encoder). - Software-only path for
x264enc,x265enc,jpegenc,openh264enc.
Image format support
- BGR8, RGB8, BGRA8, RGBA8, MONO8, MONO16 (
GRAY16_LE). - Bayer 8-bit and 16-bit encodings streamed as grayscale fallback with a throttled warning to use
image_proc/debayerfor colour output. validateImageShapevalidates width × height × step × data-size consistency before pushing frames.
Adaptive resilience
- Three-level bitrate/fps/gop adaptation loop (levels 0–2) triggered by
Degraded/Reconnectingstate transitions and recovered during sustainedStreaming. - Three adaptation profiles:
conservative,balanced,aggressive. - Configurable interval and cooldown (
runtime.adaptation.interval_ms,runtime.adaptation.cooldown_ms). - Pipeline reconfigure on adaptation policy change (stops/rebuilds engine with updated parameters).
Observability
~/runtime_status(ros2_gst_video_bridge_msgs/msg/RuntimeStatus): typed status at 1 Hz including fps_in/fps_out, drop counters split by throttle/malformed/backpressure, reconnect count, latency EWMA, push latency estimate + observed max, adaptation profile/level, and codec/encoder/fallback flags.~/runtime_events(ros2_gst_video_bridge_msgs/msg/RuntimeEvent): asynchronous events forPIPELINE_STARTED,PIPELINE_DEGRADED,RECONNECT_FAILED,ADAPTATION_APPLIED,ENCODER_FALLBACK_SW,FIRST_FAILURE_SNAPSHOT,OPERATOR_PROFILE_UPDATE, and others.~/runtime_metrics(std_msgs/msg/String): backward-compatible legacy key=value string.~/set_streaming_profile(ros2_gst_video_bridge_msgs/srv/SetStreamingProfile): operator service to switch adaptation profile and optionally reset all counters at runtime.FIRST_FAILURE_SNAPSHOTevent captures session ID, stream ID, codec, encoder, transport, sink URI, SW-fallback flag, and full effective pipeline on the first streaming failure.- Session ID (UUID-like) and stream ID are tracked across all events and status messages.
Runtime modes
stream(default): run the bridge.list_topics: print visiblesensor_msgs/msg/Imagetopics and exit.list_capabilities: rungst-inspect-1.0and report detected plugins, encoders, and sinks.validate_config: validate parameters and exit with code 0 (valid) or 1 (invalid).discover: combineslist_topics+list_capabilities.
Reconnect
- Automatic reconnect with configurable interval and optional maximum attempt limit.
- SW-fallback is attempted on reconnect if HW encoder has failed repeatedly.
pipeline_reconfigure_requested_flag ensures a newStreamEngineis created with the updated pipeline after adaptation or fallback.
Launch files
gst_video_bridge_minimal.launch.py: essential arguments only.gst_video_bridge_advanced.launch.py: full parameter surface +params_filesupport.gst_video_bridge.launch.py: compatibility wrapper.- All launches support optional
image_proc/debayernode viaenable_debayerargument.
Profile presets
- Machine profiles:
jetson,x86,raspi,generic. - Stream profiles:
default,low_latency,low_bandwidth,high_quality,monitoring_udp. - Seven curated YAML profile files under
config/profiles/.
Testing
test_config_loader: profile defaults, invalid mode rejection, alias precedence (4 tests).test_pipeline_builder: SRT/UDP h264, HW encoder (Jetson nvv4l2), h265 × 4 transports, mjpeg × 4 transports (5 tests).test_image_format: shape validation, unsupported encoding, invalid step, truncated data, Bayer grayscale fallback (5 tests).test_stream_engine: synthetic frame pushed throughappsrc → fakesinkpipeline (1 test).test_detail_utils:startsWith,extractElementName,selectSoftwareEncoderForCodec,computeAdaptationScales— 18 cases covering all profiles and edge conditions.test_metrics_publisher: counter accumulation, state reflection, adaptation/encoding metadata in publishedRuntimeStatus(9 tests).- Smoke tests:
validate_config,list_capabilities, and--show-argsfor all three launch files. - Total: 11 CTest entries (6 gtest targets + 5 smoke tests), 42 individual test cases.
Tooling
clang-format-15with.clang-format(LLVM style, 100-column limit, C++17).clang-formatdiscovered by versioned binary names inCMakeLists.txt; build continues gracefully if not found.- CI (
build-and-test+nightly-matrix) on Ubuntu 22.04 / ROS 2 Humble. - CI
clang-format-checkjob runs--dry-run --Werroron all headers and sources. - Codec/transport matrix script (
run_transport_codec_matrix.zsh) and soak script (run_soak_profile.zsh).
Documentation
docs/CONTROL_PLANE.md: topic/service contract reference.docs/DEPENDENCIES.md: required and optional apt packages, plugin checks.docs/PLATFORM_MATRIX.md: tested hardware/OS/ROS combinations.docs/TROUBLESHOOTING.md: common failure modes with diagnosis and recovery steps.README.md: full parameter reference tables with types, defaults, and descriptions.CONTRIBUTING.md: development setup, coding conventions, test requirements, PR checklist.
appsrcconfigured as non-blocking (block=false) with a bounded 2-buffer internal queue and upstream leaky policy; back-pressure drops are counted separately and do not cause a reconnect when the queue is the only error.busLoopswitched from a 100 ms blockinggst_bus_timed_pop_filteredcall (held mutex) to a non-blocking poll + 10 ms sleep, eliminating push stalls under high frame rates.- Modern
transport.*,codec.*,runtime.*parameter names always override legacygst.*aliases when both are set. - CI checkout uses
path: ws/src/ros2_gst_video_bridgematching a real colcon workspace layout. - Internal duplicate utility functions (
startsWith,extractElementName) extracted todetail/string_utils.hpp; adaptation scaling extracted todetail/adaptation.hpp; SW encoder selection todetail/encoder_selection.hpp.
busLoopmutex stall: the bus thread no longer holdsmutex_during a potentially blocking GStreamer poll.buildLegacyPayloadnow correctly declared and defined asstatic.- Redundant
encoder{""}default initializer removed fromCodecConfig. .gitignoreextended to excludeTODO*.mdpatterns.
- Jetson Orin / aarch64, Linux 5.15.148-tegra, ROS Humble, GStreamer 1.20.x.
- Basler acA2440-35uc USB3 camera at ~30 Hz BayerRG8.
- MPEG-TS/H.264 file sink validated end-to-end.
- All 11 CTest tests pass on the Jetson build.
clang-formatcheck passes on all headers and sources.
See Unreleased above. This section will be finalised when the first annotated tag is created.