{"id":48419277,"url":"https://github.com/mkassimi98/gstklvplugin","last_synced_at":"2026-04-06T08:00:55.779Z","repository":{"id":346418132,"uuid":"1189868689","full_name":"mkassimi98/gstklvplugin","owner":"mkassimi98","description":"GStreamer plugin for MISB ST 0601.8 / STANAG 4609 KLV: JSON↔KLV encode/decode, frame injection, PMT metadata signaling, plus SRT and MPEG‑TS demo pipelines in Python and C++.","archived":false,"fork":false,"pushed_at":"2026-03-23T20:31:11.000Z","size":28214,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"v1.0.0","last_synced_at":"2026-03-24T17:32:49.504Z","etag":null,"topics":["c","gst","gstreamer-plugins","klv","misb","misb-st0601","mpeg-ts","stanag","stanag4609","streaming"],"latest_commit_sha":null,"homepage":"https://www.linkedin.com/posts/mouhsine-kassimi-farhaoui-983738163_opensource-gstreamer-klv-activity-7441931945174978560-mxpJ?utm_source=share\u0026utm_medium=member_desktop\u0026rcm=ACoAACcV8nMBzQSGfcDhGqFgR-iicQR8l_p9f88","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mkassimi98.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"mkassimi98"}},"created_at":"2026-03-23T18:43:26.000Z","updated_at":"2026-03-23T22:16:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mkassimi98/gstklvplugin","commit_stats":null,"previous_names":["mkassimi98/gstklvplugin"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/mkassimi98/gstklvplugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkassimi98%2Fgstklvplugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkassimi98%2Fgstklvplugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkassimi98%2Fgstklvplugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkassimi98%2Fgstklvplugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mkassimi98","download_url":"https://codeload.github.com/mkassimi98/gstklvplugin/tar.gz/refs/heads/v1.0.0","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkassimi98%2Fgstklvplugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31464099,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T21:22:52.476Z","status":"online","status_checked_at":"2026-04-06T02:00:07.287Z","response_time":112,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","gst","gstreamer-plugins","klv","misb","misb-st0601","mpeg-ts","stanag","stanag4609","streaming"],"created_at":"2026-04-06T08:00:54.932Z","updated_at":"2026-04-06T08:00:55.771Z","avatar_url":"https://github.com/mkassimi98.png","language":"C","funding_links":["https://github.com/sponsors/mkassimi98"],"categories":[],"sub_categories":[],"readme":"# gstklvplugin\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"doc/assets/gstklvplugin_icon_v2.png\" alt=\"gstklvplugin icon\" width=\"260\" /\u003e\n\u003c/p\u003e\n\n[![C Standard](https://img.shields.io/badge/c-C11%2FGNU11-blue)](https://en.cppreference.com/w/c/11)\n[![Python Version](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org/)\n[![GStreamer](https://img.shields.io/badge/gstreamer-1.20%2B-orange)](https://gstreamer.freedesktop.org/)\n[![Build](https://img.shields.io/badge/build-meson%20%7C%20cmake-lightgrey)](meson.build)\n[![Tests](https://img.shields.io/badge/tests-gst--check-green)](tests/)\n[![Project Status](https://img.shields.io/badge/status-stable-brightgreen)](CHANGELOG.md)\n[![License](https://img.shields.io/badge/license-AGPL--3.0-blue)](LICENSE)\n\nA GStreamer 1.x plugin suite for end-to-end KLV metadata workflows. Implements **SMPTE ST 336** (KLV encoding), **MISB ST 0601.8** (UAS Datalink Local Set, 93 tags), **STANAG 4609** transport conventions, and **MISB ST 1402** MPEG-TS metadata signaling. Written in C11 for compatibility with the GStreamer plugin ecosystem.\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"doc/assets/demo.gif\" alt=\"gstklvplugin demo\" width=\"960\" height=\"540\" /\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cem\u003e\n    Demo capture running at 2 fps on purpose, so the terminal KLV output stays readable while still showing the\n    frame-by-frame relationship between video and metadata.\n  \u003c/em\u003e\n\u003c/p\u003e\n\n## Elements\n\n| Element | Type | Sink | Source | Description |\n|---|---|---|---|---|\n| `klvmetaenc` | `GstBaseTransform` | `application/json` | `meta/x-klv` | Encode JSON to MISB ST 0601 KLV |\n| `klvmetadec` | `GstBaseTransform` | `meta/x-klv` | `application/json` | Decode KLV to JSON with INI-driven scaling |\n| `klvframeinject` | `GstElement` | `video/x-h264`, `video/x-h265` | `video_src`, `klv_src` | Per-frame KLV injection synchronized to video |\n| `tspmtrewrite` | `GstBaseTransform` | `video/mpegts` | `video/mpegts` | Rewrite PMT to signal tsdemux-friendly KLVA metadata (`stream_type 0x06` in the current implementation) |\n\n---\n\n## Standards\n\n| Standard | Scope |\n|---|---|\n| SMPTE ST 336 | KLV Key-Length-Value encoding (BER lengths, UL keys) |\n| MISB ST 0601.8 | UAS Datalink Local Set — 93 tags, BCC-16 checksum |\n| STANAG 4609 | MPEG-TS motion imagery and metadata transport |\n| MISB ST 1402 | PMT metadata signaling (`metadata_descriptor 0x26`; current implementation uses `0x06 + KLVA` for GStreamer compatibility) |\n\n---\n\n## Get The Source\n\n```bash\ngit clone https://github.com/mkassimi98/gstklvplugin.git\ncd gstklvplugin\n```\n\nIf you want a specific released state instead of the current default branch:\n\n```bash\ngit clone --branch v1.0.0 --single-branch \\\n  https://github.com/mkassimi98/gstklvplugin.git\ncd gstklvplugin\n```\n\n---\n\n## Build\n\n### Prerequisites\n\n```bash\n# Meson build\nsudo apt-get install -y \\\n  meson ninja-build \\\n  libgstreamer1.0-dev \\\n  libgstreamer-plugins-base1.0-dev\n\n# Optional: C++ examples\nsudo apt-get install -y g++\n\n# Optional: repository formatting\nsudo apt-get install -y clang-format\n\n# Optional: Doxygen diagrams\nsudo apt-get install -y graphviz\n```\n\n### Meson (recommended)\n\n```bash\nmeson setup build\nmeson compile -C build\n```\n\nRun the Meson test suite:\n\n```bash\nmeson test -C build --print-errorlogs\n```\n\nOpen a build-local shell with the plugin already exported:\n\n```bash\nmeson devenv -C build\n```\n\nThat is the standard Meson-style uninstalled workflow for this repo. Inside the\nshell, `GST_PLUGIN_PATH` points at `build/src` and `KLV_TAGS_INI` points at the\nsource-tree registry.\n\n### Automatic Helpers\n\n```bash\n# Build + tests + smoke tests + Doxygen\n./scripts/check_all.sh\n\n# Apply clang-format to all tracked C/C++ files\n./scripts/run_clang_tools.sh --format\n\n# Configure/build a local dev shell wrapper\n./scripts/dev_env.sh\n\n# Configure/build/validate/install\n./scripts/install_plugin.sh --run-checks --install --prefix /usr/local\n```\n\n### CMake (alternative)\n\n```bash\nmkdir -p build \u0026\u0026 cd build\ncmake ..\ncmake --build .\n```\n\nWith C++ examples:\n\n```bash\ncmake -S . -B build \\\n  -DGSTKLVPLUGIN_BUILD_EXAMPLES=ON\ncmake --build build\n```\n\nThe CMake install path now uses `${CMAKE_INSTALL_LIBDIR}/gstreamer-1.0`, so it\nlands in the correct multiarch plugin directory on Debian-family x86 and ARM\nsystems.\n\nFormatting targets are also available from CMake:\n\n```bash\ncmake -S . -B build-cmake -DGSTKLVPLUGIN_BUILD_EXAMPLES=ON\ncmake --build build-cmake --target format\ncmake --build build-cmake --target format-check\n```\n\n### Manual System Install\n\nRecommended Meson flow:\n\n```bash\nmeson setup build --prefix /usr/local\nmeson compile -C build\nmeson test -C build --print-errorlogs\nsudo meson install -C build\n```\n\nThe GStreamer plugin directory on the current system can be queried with:\n\n```bash\npkg-config --variable=pluginsdir gstreamer-1.0\n```\n\n### Load Or Inspect The Plugin\n\n```bash\nexport GST_PLUGIN_PATH=\"$PWD/build/src:$GST_PLUGIN_PATH\"\nexport KLV_TAGS_INI=\"$PWD/data/stanag4609_tags.ini\"\n\ngst-inspect-1.0 --plugin klvplugin\ngst-inspect-1.0 klvmetaenc\ngst-inspect-1.0 klvmetadec\ngst-inspect-1.0 klvframeinject\ngst-inspect-1.0 tspmtrewrite\n```\n\nCheck visibility without printing full details:\n\n```bash\ngst-inspect-1.0 --exists klvmetaenc \u0026\u0026 echo \"klvmetaenc is available\"\n```\n\nCheck whether GStreamer blacklisted the plugin:\n\n```bash\ngst-inspect-1.0 -b\ngst-inspect-1.0 -b | rg 'gstklvplugin|klvplugin|gstklv'\n```\n\nClear the registry cache if you need to remove stale blacklist entries:\n\n```bash\nrm -f \"${XDG_CACHE_HOME:-$HOME/.cache}/gstreamer-1.0\"/registry.*.bin\n```\n\nSee [doc/installation.md](doc/installation.md) for the full install,\nvalidation, staging, and blacklist-recovery workflow, and\n[doc/packaging.md](doc/packaging.md) for `.deb` packaging. For containerized\ndevelopment and deployment patterns, see [doc/docker.md](doc/docker.md).\n\n---\n\n## Quick Start\n\n### Local roundtrip (no network)\n\nValidate all 93 MISB ST 0601.8 tags locally:\n\n```bash\nexport GST_PLUGIN_PATH=\"$PWD/build/src:$GST_PLUGIN_PATH\"\npython3 examples/test_93_tags.py\n```\n\n### SRT streaming (Python)\n\nStart the receiver first:\n\n```bash\npython3 examples/srt-pipelines/python/srt_receiver_93tags.py \\\n  --host 127.0.0.1 --port 5000\n```\n\nThen start the sender:\n\n```bash\npython3 examples/srt-pipelines/python/srt_sender_93tags.py \\\n  --host 0.0.0.0 --port 5000 --count 50\n```\n\nTransport notes:\n- Sender uses `mpegtsmux alignment=7` so TS leaves in `7 * 188 = 1316` byte chunks.\n- Receiver uses `srtsrc blocksize=1316 latency=125`, which is what made live H.264 decode reliably in practice.\n- Receiver keeps both the video sink and the KLV handoff sink clock-synchronised, so terminal prints track the displayed frame instead of arriving early.\n- For the smoothest live preview, prefer `--print-summary`; `--print-all` is heavier console I/O and can still add jitter.\n\n### UDP streaming (Python)\n\nStart the receiver first:\n\n```bash\npython3 examples/udp-pipelines/python/udp_receiver_93tags.py \\\n  --host 0.0.0.0 --port 5000\n```\n\nThen start the sender:\n\n```bash\npython3 examples/udp-pipelines/python/udp_sender_93tags.py \\\n  --host 127.0.0.1 --port 5000 --count 50\n```\n\nThe UDP receivers use the same presentation-timed output strategy as the SRT ones, so printed KLV follows the video clock instead of a separate fast metadata path.\n\n### SRT streaming (C++)\n\nBuild C++ examples:\n\n```bash\ncmake -S . -B build -DGSTKLVPLUGIN_BUILD_EXAMPLES=ON\ncmake --build build\n```\n\nThe C++ example binaries are built via CMake. Meson remains the recommended\npath for the plugin and tests, but it does not emit the example executables.\n\n```bash\n./build/gstklv_srt_receiver --host 127.0.0.1 --port 5000\n./build/gstklv_srt_sender   --host 0.0.0.0   --port 5000 --count 50\n```\n\nLike the Python receivers, the C++ SRT receiver keeps video and KLV output on the same clocked timeline.\n\n### UDP streaming (C++)\n\n```bash\n./build/gstklv_udp_receiver --host 0.0.0.0   --port 5000\n./build/gstklv_udp_sender   --host 127.0.0.1 --port 5000 --count 50\n```\n\nThe C++ UDP receiver uses the same sync strategy as the SRT receiver.\n\n### File-based TS recording (Python)\n\n```bash\npython3 examples/ts/python/klv_recorder.py \\\n  --output examples/ts/recordings/capture.ts --count 50\n\npython3 examples/ts/python/klv_video_reader.py \\\n  examples/ts/recordings/capture.ts --print-all\n```\n\nThe Python TS reader now paces KLV against playback, using the video pipeline clock when GStreamer exposes one and falling back to local PTS pacing otherwise.\n\n### File-based TS recording (C++)\n\n```bash\n./build/gstklv_ts_recorder \\\n  --output examples/ts/recordings/capture.ts --count 50\n\n./build/gstklv_ts_reader \\\n  --input examples/ts/recordings/capture.ts --print-all\n```\n\nThe C++ TS reader scans the file PMT/PES directly, tolerates both legacy `0x15` and current `0x06 + KLVA` captures, and paces KLV by PES PTS by default. Use `--no-pace` only when you want a fast metadata dump instead of playback-timed output.\n\n---\n\n## JSON Format\n\nKLV values are exchanged as flat JSON objects with numeric string keys:\n\n```json\n{\n  \"2\":  1770260492651783,\n  \"5\":  34.5,\n  \"13\": 40.63919,\n  \"14\": -73.92060,\n  \"15\": 486.7\n}\n```\n\nTags that represent local sets (nested binary structures) must be supplied as raw bytes using `hex:` or `base64:` prefixes:\n\n```json\n{\n  \"48\": \"base64:AQEA\",\n  \"73\": \"hex:01020304\"\n}\n```\n\nSee [doc/standards.md](doc/standards.md) for encoding and decoding rules.\n\n---\n\n## Pipeline Architecture\n\n### Sender\n\n```mermaid\nflowchart LR\n    A[\"videotestsrc\"] --\u003e B[\"x264enc\"]\n    B --\u003e C[\"h264parse\"]\n    C --\u003e D[\"klvframeinject\"]\n    D --\u003e|video_src| E[\"queue\"]\n    E --\u003e F[\"mpegtsmux\"]\n    D --\u003e|klv_src| G[\"queue\"]\n    G --\u003e H[\"meta/x-klv\"]\n    H --\u003e F\n    F --\u003e I[\"tspmtrewrite\"]\n    I --\u003e J[\"srtsink / udpsink\"]\n```\n\n### Receiver\n\n```mermaid\nflowchart LR\n    A[\"srtsrc / udpsrc\"] --\u003e B[\"tsdemux\"]\n    B --\u003e|video/x-h264| C[\"h264parse\"]\n    C --\u003e D[\"decoder\"]\n    D --\u003e E[\"videosink\"]\n    B --\u003e|meta/x-klv| F[\"klvmetadec\"]\n    F --\u003e G[\"JSON output\"]\n```\n\n---\n\n## MPEG-TS Signaling (ST 1402)\n\n`tspmtrewrite` rewrites the PMT after `mpegtsmux` and keeps the ST 1402 metadata descriptor fields configurable.\n\nCurrent implementation details:\n- KLV PID: `stream_type = 0x06`\n- `registration_descriptor`: `KLVA`\n- `metadata_descriptor (0x26)`: present with configurable fields\n- Rationale: GStreamer `tsdemux` expects raw KLV on `0x06 + KLVA`; plain `0x15` would require metadata access-unit wrapping that `mpegtsmux` is not producing here.\n\nVerify a captured stream:\n\n```bash\npython3 tools/capture_ts_from_srt.py \\\n  --host 127.0.0.1 --port 5000 \\\n  --output examples/ts/recordings/capture.ts --duration 5\n\npython3 tools/verify_ts_klv.py examples/ts/recordings/capture.ts --list-all\n```\n\n`verify_ts_klv.py` accepts both legacy `0x15` captures and the current `0x06 + KLVA` signaling used by this repo.\n\n---\n\n## Testing\n\n### gst-check (Meson)\n\n```bash\nmeson setup build\nmeson compile -C build\nmeson test -C build --print-errorlogs\n```\n\nCovers nine Meson suites by default:\n- element tests for `klvmetaenc`, `klvmetadec`, `klvframeinject`, and `tspmtrewrite`\n- utility tests for KLV helpers and MPEG-TS PSI helpers\n- smoke tests for TS record/read and UDP loopback using the Python examples\n- a staged-install smoke that validates plugin discovery from a clean registry outside the build tree\n\nWhen `cmake` is available, the suite also adds a C++ TS roundtrip smoke for the example binaries.\n\n`doc/tests.md` describes the suite layout, smoke coverage, and the GStreamer\ntesting APIs used (`gstreamer-check`, `GstHarness`, and pipeline-level checks\nwhere multi-pad behaviour is under test).\n\nMeson is the only supported test runner now. CMake remains available for building the plugin and the C++ example applications.\n\n---\n\n## Configuration\n\n| Variable | Purpose |\n|---|---|\n| `GST_PLUGIN_PATH` | Directory containing `gstklvplugin.so` |\n| `KLV_TAGS_INI` | Override path to `stanag4609_tags.ini` |\n| `KLV_DEBUG` | Enable verbose KLV logging in `klvframeinject` |\n| `GST_DEBUG` | Standard GStreamer debug level (e.g. `GST_DEBUG=3`) |\n\nTag registry locations:\n\n- Source tree: `data/stanag4609_tags.ini`\n- Installed builds: `${prefix}/share/gstklvplugin/stanag4609_tags.ini`\n\n---\n\n## Documentation\n\n| Document | Description |\n|---|---|\n| [doc/index.md](doc/index.md) | Documentation landing page and architecture map |\n| [doc/installation.md](doc/installation.md) | Manual and automatic build/install workflows, discovery, and blacklist recovery |\n| [doc/docker.md](doc/docker.md) | Docker integration guide for development, runtime images, networking, and troubleshooting |\n| [doc/packaging.md](doc/packaging.md) | Debian/Raspberry Pi packaging and distribution workflow |\n| [doc/standards.md](doc/standards.md) | Standards, encoding rules, and compliance scope |\n| [doc/klv_tags.md](doc/klv_tags.md) | Full MISB ST 0601.8 tag registry table |\n| [doc/code_reference.md](doc/code_reference.md) | Module layout, key functions, and data flow |\n| [doc/design_decisions.md](doc/design_decisions.md) | Rationale behind key design choices |\n| [doc/compliance_appendix.md](doc/compliance_appendix.md) | PMT descriptor bytes and verification steps |\n| [doc/examples.md](doc/examples.md) | Example workflows (Python and C++) |\n| [doc/93_tags.md](doc/93_tags.md) | Full 93-tag ST 0601.8 workflow |\n| [doc/srt_pipelines.md](doc/srt_pipelines.md) | SRT pipeline composition and options |\n| [doc/tests.md](doc/tests.md) | Test suite documentation |\n| [doc/doxygen_main.md](doc/doxygen_main.md) | Doxygen API reference entry point |\n| [doc/plugin_usage_guide.md](doc/plugin_usage_guide.md) | Integration guide for Python and C++ applications |\n\n### API Reference (Doxygen)\n\n```bash\n./scripts/run_doxygen.sh --strict\n# Open: doc/doxygen/html/index.html\n```\n\n---\n\n## Project Files\n\n| File | Description |\n|---|---|\n| `LICENSE` | GNU AGPL-3.0 |\n| `AUTHORS` | Maintainers and contributors |\n| `CHANGELOG.md` | Release history |\n| `CONTRIBUTING.md` | Contribution guide |\n| `CODE_OF_CONDUCT.md` | Community standards (Contributor Covenant v2.1) |\n| `SECURITY.md` | Vulnerability reporting policy |\n| `meson.build` | Meson build definition |\n| `CMakeLists.txt` | CMake build definition |\n| `Doxyfile` | Doxygen configuration |\n| `data/stanag4609_tags.ini` | Authoritative tag registry |\n\n---\n\n## Author\n\n**Mouhsine Kassimi Farhaoui** — [mouhsine98@gmail.com](mailto:mouhsine98@gmail.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkassimi98%2Fgstklvplugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmkassimi98%2Fgstklvplugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkassimi98%2Fgstklvplugin/lists"}