diff --git a/pkgs/development/libraries/gstreamer/rs/default.nix b/pkgs/development/libraries/gstreamer/rs/default.nix index 4a77e4a43e8d..01beb2532886 100644 --- a/pkgs/development/libraries/gstreamer/rs/default.nix +++ b/pkgs/development/libraries/gstreamer/rs/default.nix @@ -13,9 +13,12 @@ lld, nasm, cmake, + libGL, gstreamer, gst-plugins-base, + gst-plugins-good, gst-plugins-bad, + gst-plugins-ugly, gtk4, cairo, csound, @@ -24,7 +27,11 @@ libwebp, openssl, pango, - gst-plugins-good, + + jq, + writeTextFile, + validatePkgConfig, + testers, nix-update-script, # specifies a limited subset of plugins to build (the default `null` means all plugins supported on the stdenv platform) plugins ? null, @@ -36,33 +43,33 @@ }: let - # populated from meson_options.txt (manually for now, but that might change in the future) + # checked against upstream meson_options.txt in postConfigure + # ordered according plugin list in README.md for readability + # validate plugin is excluded here and in the verification script below validPlugins = { - # audio - audiofx = [ ]; - claxon = [ ]; - csound = [ csound ]; - lewton = [ ]; - spotify = [ ]; - # generic file = [ ]; + gopbuffer = [ ]; + inter = [ ]; + originalbuffer = [ ]; + streamgrouper = [ ]; sodium = [ libsodium ]; threadshare = [ ]; - # mux - flavors = [ ]; - fmp4 = [ ]; - mp4 = [ ]; - # net aws = [ openssl ]; + deepgram = [ ]; + hlsmultivariantsink = [ ]; hlssink3 = [ ]; + icecast = [ ]; + mpegtslive = [ ]; ndi = [ ]; onvif = [ pango ]; + quinn = [ ]; raptorq = [ ]; reqwest = [ openssl ]; rtp = [ ]; + rtsp = [ ]; webrtc = [ gst-plugins-bad openssl @@ -72,18 +79,17 @@ let openssl ]; - # text - textahead = [ ]; - json = [ ]; - regex = [ ]; - textwrap = [ ]; - - # utils - fallbackswitch = [ gtk4 ]; - livesync = [ gtk4 ]; - togglerecord = [ gtk4 ]; - tracers = [ ]; - uriplaylistbin = [ ]; + # audio + audiofx = [ ]; + audioparsers = [ ]; + claxon = [ ]; + csound = [ csound ]; + demucs = [ ]; + elevenlabs = [ ]; + lewton = [ ]; + speechmatics = [ ]; + spotify = [ ]; + whisper = [ ]; # video cdg = [ ]; @@ -95,8 +101,34 @@ let hsv = [ ]; png = [ ]; rav1e = [ ]; + skia = [ ]; videofx = [ cairo ]; + # would require libvvdec + vvdec = [ ]; webp = [ libwebp ]; + + # mux + flavors = [ ]; + isobmff = [ ]; + + # text + textaccumulate = [ ]; + textahead = [ ]; + json = [ ]; + regex = [ ]; + textwrap = [ ]; + + # utils + fallbackswitch = [ gtk4 ]; + livesync = [ gtk4 ]; + togglerecord = [ gtk4 ]; + tracers = [ ]; + uriplaylistbin = [ ]; + debugseimetainserter = [ ]; + + # analytics + analytics = [ gst-plugins-bad ]; + burn = [ ]; }; selectedPlugins = @@ -105,8 +137,16 @@ let else lib.subtractLists ( [ - "csound" # tests have weird failure on x86, does not currently work on arm or darwin - "livesync" # tests have suspicious intermittent failure, see https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/issues/357 + # tests have weird failure on x86, does not currently work on arm or darwin + # csound rust package currently incompatible with csound >= 7.x + "csound" + + # test failures + "isobmff" + "webrtc" + + "vvdec" # libvvdec not currently packaged + "skia" # skia-bindings requires configuration to link against system libraries ] ++ lib.optionals stdenv.hostPlatform.isAarch64 [ "raptorq" # pointer alignment failure in tests on aarch64 @@ -126,7 +166,43 @@ let ] ) (lib.attrNames validPlugins); + rsPrefixedPlugins = [ + "analytics" + "audiofx" + "audioparsers" + "closedcaption" + "file" + "inter" + "onvif" + "png" + "rtp" + "rtsp" + "tracers" + "videofx" + "webp" + "webrtc" + ]; + + pkgConfigName = + name: + if name == "flavors" then + "gstrsflv" + else + (if lib.elem name rsPrefixedPlugins then "gstrs${name}" else "gst${name}"); + pkgConfigNames = map pkgConfigName selectedPlugins; + invalidPlugins = lib.subtractLists (lib.attrNames validPlugins) selectedPlugins; + + validPluginFile = writeTextFile { + name = "known-plugin-names.txt"; + text = lib.concatLines (lib.attrNames validPlugins); + }; + + # aws-lc-rs has no pregenerated bindings for exotic platforms + # https://aws.github.io/aws-lc-rs/platform_support.html + # whisper requires bindgen + requiresBindgen = + !(stdenv.hostPlatform.isx86 || stdenv.hostPlatform.isAarch64) || lib.elem "whisper" selectedPlugins; in assert lib.assertMsg (invalidPlugins == [ ]) "Invalid gst-plugins-rs plugin${ @@ -135,7 +211,7 @@ assert lib.assertMsg (invalidPlugins == [ ]) stdenv.mkDerivation (finalAttrs: { pname = "gst-plugins-rs"; - version = "0.14.4"; + version = "0.15.3"; outputs = [ "out" @@ -147,15 +223,32 @@ stdenv.mkDerivation (finalAttrs: { owner = "gstreamer"; repo = "gst-plugins-rs"; rev = finalAttrs.version; - hash = "sha256-MZyYHMq6gFJkVxlrmeXUjOmRYsQBHj0848cnF+7mtbU="; + hash = "sha256-DO5Dk9xjqWTI4ORzlHYPc/O/tyHfSyh7+YCzES5ZiHs="; }; cargoDeps = rustPlatform.fetchCargoVendor { inherit (finalAttrs) src; name = "gst-plugins-rs-${finalAttrs.version}"; - hash = "sha256-T+fdu+Oe07Uf1YoRGYl2DMb1QgdSZVLwcOqH4bBNGXU="; + hash = "sha256-EHikshVeaBzyx9+GBIkOPii63T12BobWdW6nTBLzwU8="; }; + postConfigure = '' + meson introspect . --buildoptions | \ + ${lib.getExe jq} -r 'map(select(.description | test("Build .+ plugin")) | .name | select(. != "validate")) | sort | .[]' \ + > valid-plugin-names.txt + echo "checking for consistency between validPlugins and meson_options.txt" + diff -u ${validPluginFile} valid-plugin-names.txt + ''; + + patches = [ + ./doctest-fixes.patch + ]; + + postPatch = '' + patchShebangs cargo_wrapper.py dependencies.py + ''; + + __structuredAttrs = true; strictDeps = true; nativeBuildInputs = [ @@ -169,10 +262,9 @@ stdenv.mkDerivation (finalAttrs: { cargo cargo-c nasm + validatePkgConfig ] - # aws-lc-rs has no pregenerated bindings for exotic platforms - # https://aws.github.io/aws-lc-rs/platform_support.html - ++ lib.optionals (!(stdenv.hostPlatform.isx86 || stdenv.hostPlatform.isAarch64)) [ + ++ lib.optionals requiresBindgen [ cmake rustPlatform.bindgenHook ] @@ -188,6 +280,7 @@ stdenv.mkDerivation (finalAttrs: { buildInputs = [ gstreamer gst-plugins-base + libGL ] ++ lib.optionals stdenv.hostPlatform.isDarwin [ apple-sdk_gstreamer @@ -197,6 +290,7 @@ stdenv.mkDerivation (finalAttrs: { checkInputs = [ gst-plugins-good gst-plugins-bad + gst-plugins-ugly ]; mesonFlags = (map (plugin: lib.mesonEnable plugin true) selectedPlugins) ++ [ @@ -211,24 +305,25 @@ stdenv.mkDerivation (finalAttrs: { doCheck = stdenv.buildPlatform.canExecute stdenv.hostPlatform; # csound lib dir must be manually specified for it to build - preConfigure = '' - export CARGO_BUILD_JOBS=$NIX_BUILD_CORES - - patchShebangs dependencies.py - '' - + lib.optionalString (lib.elem "csound" selectedPlugins) '' + preConfigure = lib.optionalString (lib.elem "csound" selectedPlugins) '' export CSOUND_LIB_DIR=${lib.getLib csound}/lib ''; mesonCheckFlags = [ "--verbose" ]; + # required for icecast tests + __darwinAllowLocalNetworking = + finalAttrs.finalPackage.doCheck && lib.elem "icecast" selectedPlugins; + preCheck = '' # Fontconfig error: No writable cache directories - export XDG_CACHE_HOME=$(mktemp -d) + export XDG_CACHE_HOME="$(mktemp -d)" + export GST_PLUGIN_PATH="$(realpath "target/${stdenv.hostPlatform.rust.cargoShortTarget}/$cargoBuildType")" + export GST_PLUGIN_SCANNER="${lib.getLib gstreamer}/libexec/gstreamer-1.0/gst-plugin-scanner" ''; postInstall = '' - install -Dm444 -t ''${!outputDev}/lib/pkgconfig gst*.pc + install -Dm444 -t ''${!outputDev}/lib/pkgconfig plugins/gst*.pc ''; doInstallCheck = @@ -240,6 +335,10 @@ stdenv.mkDerivation (finalAttrs: { ''; passthru = { + tests.pkg-config = testers.hasPkgConfigModules { + package = finalAttrs.finalPackage; + versionCheck = true; + }; updateScript = nix-update-script { # use numbered releases rather than gstreamer-* releases # this matches upstream's recommendation: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/issues/470#note_2202772 @@ -262,5 +361,6 @@ stdenv.mkDerivation (finalAttrs: { ]; platforms = lib.platforms.unix; maintainers = with lib.maintainers; [ tmarkus ]; + pkgConfigModules = pkgConfigNames; }; }) diff --git a/pkgs/development/libraries/gstreamer/rs/doctest-fixes.patch b/pkgs/development/libraries/gstreamer/rs/doctest-fixes.patch new file mode 100644 index 000000000000..5ada0c1409c5 --- /dev/null +++ b/pkgs/development/libraries/gstreamer/rs/doctest-fixes.patch @@ -0,0 +1,98 @@ +diff --git a/audio/elevenlabs/src/synthesizer/imp.rs b/audio/elevenlabs/src/synthesizer/imp.rs +index c31cb4f4d..a55b4fbb6 100644 +--- a/audio/elevenlabs/src/synthesizer/imp.rs ++++ b/audio/elevenlabs/src/synthesizer/imp.rs +@@ -21,7 +21,7 @@ + //! + //! Example usage with srt file as input: + //! +-//! ``` ++//! ```sh + //! gst-launch-1.0 filesrc location=/home/meh/Documents/chaplin-fr-shifted.srt ! \ + //! subparse ! clocksync ! queue ! \ + //! elevenlabssynthesizer voice-id=kENkNtk0xyzG09WW40xE overflow=shift api-key=XXX ! autoaudiosink +diff --git a/audio/whisper/src/transcriber/imp.rs b/audio/whisper/src/transcriber/imp.rs +index 28e5446ce..939a66138 100644 +--- a/audio/whisper/src/transcriber/imp.rs ++++ b/audio/whisper/src/transcriber/imp.rs +@@ -34,21 +34,21 @@ + * The element re-exports the features exposed by the whisper-rs crate to select backends, this is + * an example for building the element with CUDA support enabled: + * +- * ``` ++ * ```sh + * cargo build --features=cuda + * ``` + * + * You can download models using the [whisper.cpp download script], this is an example for + * downloading the large-v3 model: + * +- * ``` ++ * ```sh + * ./download-ggml-model.sh large-v3 + * ``` + * + * Equipped with this, this is an example for running live inference with the element introducing a + * 6 seconds latency: + * +- * ``` ++ * ```sh + * gst-launch-1.0 filesrc location=/home/meh/Music/chaplin.wav ! \ + * wavparse ! audioconvert ! audioresample ! clocksync ! \ + * queue max-size-time=5000000000 max-size-buffers=0 max-size-bytes=0 ! \ +diff --git a/utils/debugseimetainserter/src/debugseimetainserter/mod.rs b/utils/debugseimetainserter/src/debugseimetainserter/mod.rs +index a1d8d83ed..e090c6afd 100644 +--- a/utils/debugseimetainserter/src/debugseimetainserter/mod.rs ++++ b/utils/debugseimetainserter/src/debugseimetainserter/mod.rs +@@ -12,7 +12,7 @@ + * Adds GstVideoSEIUserDataUnregisteredMeta to video buffers for testing SEI insertion. + * + * ## Example launch line +- * ``` ++ * ```sh + * gst-launch-1.0 videotestsrc ! x264enc ! h264parse ! \ + * debugseimetainserter uuid=12345678-1234-1234-1234-123456789abc data="test payload" ! \ + * h264seiinserter ! filesink location=output.h264 +diff --git a/utils/tracers/src/pipeline_snapshot/imp.rs b/utils/tracers/src/pipeline_snapshot/imp.rs +index 6e4d5c54e..cccfbdc82 100644 +--- a/utils/tracers/src/pipeline_snapshot/imp.rs ++++ b/utils/tracers/src/pipeline_snapshot/imp.rs +@@ -33,23 +33,23 @@ + * - `dot-prefix` (string, default: "pipeline-snapshot-"): when dumping pipelines to a `dot` file each file is named `$prefix$pipeline_name.dot`. + * - `dot-ts` (boolean, default: "true"): if the current timestamp should be added as a prefix to each pipeline `dot` file. + * - `cleanup-mode` (enum, default: "none"): Determines how .dot files are cleaned up: +- * - "initial": Removes all existing .dot files from the target folder when the tracer starts +- * - "automatic": Performs cleanup before each snapshot. If folder-mode is enabled, cleans up .dot files within folders. +- * If folder-mode is None, cleans up .dot files directly in the target directory +- * - "none": Never removes any .dot files ++ * - "initial": Removes all existing .dot files from the target folder when the tracer starts ++ * - "automatic": Performs cleanup before each snapshot. If folder-mode is enabled, cleans up .dot files within folders. ++ * if folder-mode is None, cleans up .dot files directly in the target directory ++ * - "none": Never removes any .dot files + * - `folder-mode` (enum, default: "none"): Controls how .dot files are organized in folders: +- * - "none": All .dot files are stored directly in the target directory without subfolder organization +- * - "numbered": Creates a new numbered folder (starting from 0) for each snapshot operation +- * - "timed": Creates a new folder named with the current timestamp for each snapshot operation ++ * - "none": All .dot files are stored directly in the target directory without subfolder organization ++ * - "numbered": Creates a new numbered folder (starting from 0) for each snapshot operation ++ * - "timed": Creates a new folder named with the current timestamp for each snapshot operation + * - `dots-viewer-websocket-url`: A websocket URL to connect to a dots-viewer server instance, +- * allowing the user to snapshot running pipelines from the web +-* page. To trigger a snapshot, the user should send a json message +-* with the following format: +-* ```json +-* { +-* "type": "Snapshot" +-* } +-* ``` ++ * allowing the user to snapshot running pipelines from the web ++ * page. To trigger a snapshot, the user should send a json message ++ * with the following format: ++ * ```json ++ * { ++ * "type": "Snapshot" ++ * } ++ * ``` + * + * Examples: + *