diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96dace4..182fdd3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -133,13 +133,14 @@ jobs: # Build the gst-plugins-rs elements the sync tests need — st2038extractor / # st2038combiner (closedcaption), rtpsmpte291pay / rtpsmpte291depay (rtp) and # udpsrc2 / rtpjxsv — pinned main commit that carries udpsrc2, rtpjxsv - # pay/depay, the st2038combiner skew fix, and rtpsmpte291depay multi-ANC - # fixes; put them on GST_PLUGIN_PATH so the udp av_sync case (and udp2 / - # jxsv tests) run here instead of self-skipping. The mxl and nvdsudp cases - # still self-skip (no libmxl / DeepStream on the runner). + # pay/depay, the st2038combiner skew fix, rtpsmpte291depay multi-ANC + # fixes, and the st2038 ST 291 ADF parity fix; put them on GST_PLUGIN_PATH + # so the udp av_sync case (and udp2 / jxsv tests) run here instead of + # self-skipping. The mxl and nvdsudp cases still self-skip (no libmxl / + # DeepStream on the runner). - name: Build gst-plugins-rs plugins (pinned) env: - GST_PLUGINS_RS_REF: 0332d3d2084df7bae6dbd3c924a2bb62c2e56e89 + GST_PLUGINS_RS_REF: 8fe3cc1195d7d54990a84d85ca189624db29b096 RUSTUP_TOOLCHAIN: "1.92" run: | git init "${RUNNER_TEMP}/gst-plugins-rs" diff --git a/docker/gst-nmos-rs/Dockerfile b/docker/gst-nmos-rs/Dockerfile index f194762..ca586e5 100644 --- a/docker/gst-nmos-rs/Dockerfile +++ b/docker/gst-nmos-rs/Dockerfile @@ -5,11 +5,13 @@ # transport=mxl — gst-mxl-rs (mxlsrc/mxlsink) # transport=udp — gst-plugins-good (udpsrc/udpsink + rtp*pay/depay) # transport=udp2 — gst-plugins-rs (udpsrc2 + rtp*pay2/rtp*depay2; falls back to gst-plugins-good) +# ancillary data — gst-plugins-rs closedcaption (st2038extractor / st2038combiner) +# A/V sync testing — gst-avsynctest-rs (avsyncvideotestsrc / avsyncaudiotestsrc) # # Build from the repository root: # docker build -f docker/gst-nmos-rs/Dockerfile -t nvnmos-gst . # -# Optional extra distro packages (space-separated apt names), e.g. gst-plugins-bad/-ugly plugins: +# Optional extra distro packages (space-separated apt names), e.g. gst-plugins-bad/-ugly: # docker build -f docker/gst-nmos-rs/Dockerfile -t nvnmos-gst \ # --build-arg EXTRA_APT_PACKAGES="gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly" . # @@ -36,7 +38,7 @@ ARG RUST_TOOLCHAIN=1.92 ARG MXL_REPO=https://github.com/dmf-mxl/mxl.git ARG MXL_REF=81738a15adb55119a6855343bc1053a4389bf6df ARG GST_PLUGINS_RS_REPO=https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git -ARG GST_PLUGINS_RS_REF=0332d3d2084df7bae6dbd3c924a2bb62c2e56e89 +ARG GST_PLUGINS_RS_REF=8fe3cc1195d7d54990a84d85ca189624db29b096 # Final image arguments ARG NVNMOS_UID=10001 @@ -172,11 +174,12 @@ COPY rust/ /nvnmos/rust/ WORKDIR /nvnmos RUN NVNMOS_LIB_DIR=/nvnmos/build \ cargo build --manifest-path rust/Cargo.toml \ - -p nvnmosd -p gst-nmos-rs \ + -p nvnmosd -p gst-nmos-rs -p gst-avsynctest-rs \ --release --locked # ----------------------------------------------------------------------------- -# gst-plugins-rs — udpsrc2 (udp2) and rtp*pay2 / *depay2 / rtpsmpte291*. +# gst-plugins-rs — udpsrc2, rtp*pay2 / *depay2 (for udp2), and +# st2038extractor / st2038combiner (for ST 2110-40 / RFC 8331 / ST 291 ANC). # ----------------------------------------------------------------------------- FROM ${BASE_IMAGE} AS gst-plugins-rs-builder @@ -190,9 +193,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ curl \ git \ + libcairo2-dev \ libglib2.0-dev \ libgstreamer-plugins-base1.0-dev \ libgstreamer1.0-dev \ + libpango1.0-dev \ libssl-dev \ pkg-config \ && rm -rf /var/lib/apt/lists/* \ @@ -209,7 +214,7 @@ RUN git init /gst-plugins-rs && cd /gst-plugins-rs \ && git checkout FETCH_HEAD WORKDIR /gst-plugins-rs -RUN cargo cbuild -p gst-plugin-udp -p gst-plugin-rtp --release +RUN cargo cbuild -p gst-plugin-udp -p gst-plugin-rtp -p gst-plugin-closedcaption --release # ----------------------------------------------------------------------------- # Stage runtime libraries and binaries into a fixed layout under /opt/nvnmos. @@ -221,17 +226,22 @@ COPY --from=nvnmos-cpp-builder /nvnmos/build/libnvnmos.so /nvnmos-lib/ COPY --from=mxl-builder /mxl/install/lib /mxl-lib COPY --from=nvnmos-rust-builder /nvnmos/rust/target/release/nvnmosd /bin/nvnmosd COPY --from=nvnmos-rust-builder /nvnmos/rust/target/release/libgstnmos.so /plugins/ +COPY --from=nvnmos-rust-builder /nvnmos/rust/target/release/libgstavsynctest.so /plugins/ COPY --from=mxl-builder /mxl/rust/target/release/libgstmxl.so /plugins/ COPY --from=gst-plugins-rs-builder \ /gst-plugins-rs/target/x86_64-unknown-linux-gnu/release/libgstrsudp.so /plugins/ COPY --from=gst-plugins-rs-builder \ /gst-plugins-rs/target/x86_64-unknown-linux-gnu/release/libgstrsrtp.so /plugins/ +COPY --from=gst-plugins-rs-builder \ + /gst-plugins-rs/target/x86_64-unknown-linux-gnu/release/libgstrsclosedcaption.so /plugins/ RUN mkdir -p /opt/nvnmos/bin /opt/nvnmos/lib /opt/nvnmos/lib/mxl/internal \ /opt/nvnmos/plugins \ && cp /bin/nvnmosd /opt/nvnmos/bin/ \ && cp /plugins/libgstnmos.so /plugins/libgstmxl.so \ - /plugins/libgstrsudp.so /plugins/libgstrsrtp.so /opt/nvnmos/plugins/ \ + /plugins/libgstrsudp.so /plugins/libgstrsrtp.so \ + /plugins/libgstrsclosedcaption.so \ + /plugins/libgstavsynctest.so /opt/nvnmos/plugins/ \ && cp -a /nvnmos-lib/. /opt/nvnmos/lib/ \ && cp -a /mxl-lib/. /opt/nvnmos/lib/mxl/ \ && if [ -d /opt/nvnmos/lib/mxl/internal ]; then :; \ @@ -283,6 +293,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gstreamer1.0-plugins-base \ gstreamer1.0-plugins-good \ gstreamer1.0-tools \ + libpangocairo-1.0-0 \ ${EXTRA_APT_PACKAGES} \ && rm -rf /var/lib/apt/lists/* diff --git a/docker/gst-nmos-rs/README.md b/docker/gst-nmos-rs/README.md index f1bd9b8..240813b 100644 --- a/docker/gst-nmos-rs/README.md +++ b/docker/gst-nmos-rs/README.md @@ -5,7 +5,12 @@ SPDX-License-Identifier: Apache-2.0 # gst-nmos-rs Container Image -Operator runtime image: `nvnmosd`, `gst-nmos-rs` (`libgstnmos.so`), MXL (`libmxl` + `libgstmxl.so`), and GStreamer plugins for **linux/amd64** (default base `ubuntu:24.04`, non-root UID/GID **10001**). +Operator runtime image for **linux/amd64** (default base `ubuntu:24.04`, non-root UID/GID **10001**): + +- `nvnmosd`, `gst-nmos-rs` (`libgstnmos.so`) +- MXL (`libmxl` + `libgstmxl.so`) +- A/V sync testing — `gst-avsynctest-rs` (`avsyncvideotestsrc` / `avsyncaudiotestsrc`) +- Ancillary data — `gst-plugins-rs` closedcaption (`st2038extractor` / `st2038combiner`) for ST 2110-40 / RFC 8331 / ST 291 ANC Use this image to run `gst-launch-1.0` pipelines with `nmossrc` / `nmossink`: @@ -33,13 +38,13 @@ The nvnmos tree is taken from the build context (`COPY src/`, `COPY rust/` via t | `RUST_TOOLCHAIN` | `1.92` | Rust toolchain for all Rust stages in this image. Matches [`rust/rust-toolchain.toml`](../../rust/rust-toolchain.toml); gst-plugins-rs MSRV is **1.92**. Workspace MSRV is **1.87** in [`rust/Cargo.toml`](../../rust/Cargo.toml). | | `MXL_REPO` | `https://github.com/dmf-mxl/mxl.git` | MXL source repository (`libmxl`, `gst-mxl-rs`). | | `MXL_REF` | `81738a15adb55119a6855343bc1053a4389bf6df` | Pinned MXL commit (`81738a1`, tip of `release/v1.1` at time of writing). Use a full 40-character SHA or a branch/tag name. | -| `GST_PLUGINS_RS_REPO` | `https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git` | gst-plugins-rs source for `transport=udp2`. | -| `GST_PLUGINS_RS_REF` | `0332d3d2084df7bae6dbd3c924a2bb62c2e56e89` | Pinned gst-plugins-rs commit on `main` (`udpsrc2`, `rtpjxsv` pay/depay, `st2038combiner` skew and `rtpsmpte291depay` multi-ANC fixes). Builds `gst-plugin-udp` + `gst-plugin-rtp`. Use a full 40-character SHA or a branch/tag name. | +| `GST_PLUGINS_RS_REPO` | `https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git` | gst-plugins-rs source. | +| `GST_PLUGINS_RS_REF` | `8fe3cc1195d7d54990a84d85ca189624db29b096` | Pinned gst-plugins-rs commit on `main` (`udpsrc2`, `rtpjxsv` pay/depay, `st2038combiner` skew, `rtpsmpte291depay` multi-ANC, and `st2038` ST 291 ADF parity fixes). Builds `gst-plugin-udp` + `gst-plugin-rtp` + `gst-plugin-closedcaption`. Use a full 40-character SHA or a branch/tag name. | | `NVNMOS_UID` | `10001` | Fixed runtime user UID (`nvnmos`). | | `NVNMOS_GID` | `10001` | Fixed runtime group GID (`nvnmos`). | | `EXTRA_APT_PACKAGES` | *(empty)* | Optional space-separated apt package names added in the final image stage (e.g. `gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly`). Installed to the default GStreamer plugin path. | -Example with extra plugins: +Example with extra apt packages: ```bash docker build -f docker/gst-nmos-rs/Dockerfile -t nvnmos-gst \ @@ -61,6 +66,21 @@ NGC pull may require `docker login nvcr.io`. Pin the DeepStream tag you need. Th CI builds and smoke-tests only the default Ubuntu-based `docker/nvnmos` package image, not a DeepStream or Rivermax `gst-nmos-rs` variant. +### Optional GStreamer codecs on DeepStream + +On the default Ubuntu base, `--build-arg EXTRA_APT_PACKAGES="gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly"` is enough to make elements such as `srtsink` and `x264enc` available. On DeepStream 9.1 those packages are already installed, but `x264enc` still does not load until you run DeepStream's restore script (it reinstalls the plugins and missing codec libraries such as `libx264`). + +In a **derived** image: + +```dockerfile +# Example only — not part of this repository's Dockerfiles. +FROM nvnmos-gst:ds +USER root +RUN /opt/nvidia/deepstream/deepstream/user_additional_install.sh \ + && rm -rf /var/lib/apt/lists/* +USER nvnmos +``` + ### Rivermax for `transport=nvdsudp` DeepStream plugins alone are not enough for `transport=nvdsudp`. You also need the [Rivermax SDK](https://developer.nvidia.com/networking/rivermax) libraries in the image, a Rivermax license at runtime, a ConnectX-5 (or newer) NIC, and host MOFED drivers. Pipeline property details are in the [DeepStream Rivermax pipeline examples](../../rust/gst-nmos-rs/pipeline-examples.md#deepstream-rivermax). @@ -144,7 +164,7 @@ One container per pod; pass the pipeline as `args`. Mount a volume and set `mxl- | `NVNMOSD_UDS` | `/tmp/nvnmosd.sock` | `nvnmosd` Unix socket; must match `daemon-uri=unix:…` in the pipeline | | `NVNMOS_PUBLISH_MDNS` | `1` | Publish `${HOSTNAME}.local`; set `0` to disable | -The entrypoint sets `LD_LIBRARY_PATH` and `GST_PLUGIN_PATH` for the fixed install under `/opt/nvnmos/plugins` (`libgstnmos.so`, `libgstmxl.so`, `libgstrsudp.so`, `libgstrsrtp.so`). System gst-plugins-good/-base remain on the default GStreamer search path for `transport=udp`. +The entrypoint sets `LD_LIBRARY_PATH` and `GST_PLUGIN_PATH` for the fixed install under `/opt/nvnmos/plugins` (`libgstnmos.so`, `libgstmxl.so`, `libgstrsudp.so`, `libgstrsrtp.so`, `libgstrsclosedcaption.so`, `libgstavsynctest.so`). System gst-plugins-good/-base remain on the default GStreamer search path for `transport=udp`. ## Shared Infrastructure