diff --git a/flake.nix b/flake.nix index bb0b4f2..2ae8f66 100644 --- a/flake.nix +++ b/flake.nix @@ -67,7 +67,7 @@ overlays = [ agenix.overlays.default (import ./overlays/gnome.nix) - (import ./overlays/default.nix) + (import ./overlays/libcamera.nix) ( final: prev: { unstable = import inputs.nixpkgs-unstable { system = final.system; }; @@ -151,14 +151,22 @@ path = deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.vps1; }; }; - # pi = { - # hostname = "10.0.1.191"; - # - # profiles.system = { - # user = "root"; - # path = deploy-rs.lib.aarch64-linux.activate.nixos self.nixosConfigurations.pi; - # }; - # }; + pi = { + hostname = "10.0.1.191"; + + profiles.system = { + user = "root"; + path = deploy-rs.lib.aarch64-linux.activate.nixos self.nixosConfigurations.pi; + }; + }; + skycam = { + hostname = "10.0.1.146"; + + profiles.system = { + user = "root"; + path = deploy-rs.lib.aarch64-linux.activate.nixos self.nixosConfigurations.skycam; + }; + }; }; }; diff --git a/hosts/skycam/README.md b/hosts/skycam/README.md index de64288..29f932d 100644 --- a/hosts/skycam/README.md +++ b/hosts/skycam/README.md @@ -20,3 +20,10 @@ SD card | `/dev/mmcblk0` (ext4, NixOS Root) ## Devices and connections - Camera Module 3 with wide-angle lens +## Building +To generate a compressed SD card image for Skycam, run: +`nix build '.#nixosConfigurations.skycam.config.system.build.sdImage'` + +Once a card is imaged, the existing SSH host keys should be copied to +`/etc/ssh` manually to enable secret decryption. + diff --git a/hosts/skycam/default.nix b/hosts/skycam/default.nix index 31c542b..4b6cad4 100644 --- a/hosts/skycam/default.nix +++ b/hosts/skycam/default.nix @@ -42,7 +42,6 @@ }; firmware = with pkgs; [ firmwareLinuxNonfree - wireless-regdb ]; }; @@ -67,13 +66,31 @@ services.openssh.settings.PermitRootLogin = lib.mkForce "prohibit-password"; + systemd.services.ustreamer = { + enable = true; + description = "uStreamer service"; + unitConfig = { + Type = "simple"; + ConditionPathExists = "/sys/bus/i2c/drivers/imx708/10-001a/video4linux"; + }; + serviceConfig = { + ExecStart = ''${pkgs.libcamera}/bin/libcamerify ${pkgs.unstable.ustreamer}/bin/ustreamer \ + --host=0.0.0.0 \ + --resolution=4608x2592 + ''; + Restart = "always"; + RestartSec = 10; + }; + wantedBy = [ "network-online.target" ]; + confinement.mode = "chroot-only"; + }; + environment.systemPackages = with pkgs; [ - camera-streamer git neovim + libcamera libraspberrypi raspberrypi-eeprom - rpicam-apps v4l-utils unstable.ustreamer ]; diff --git a/hosts/skycam/hardware-configuration.nix b/hosts/skycam/hardware-configuration.nix index 65f519a..a3a3728 100644 --- a/hosts/skycam/hardware-configuration.nix +++ b/hosts/skycam/hardware-configuration.nix @@ -7,9 +7,12 @@ boot = { kernelModules = [ "bcm2835-v4l2" ]; - kernelParams = [ "cma=512M" ]; - supportedFilesystems = lib.mkForce [ "f2fs" "vfat xfs" ]; - tmp.cleanOnBoot = true; + kernelParams = [ + "cma=512M" + "panic=0" + ]; + supportedFilesystems = lib.mkForce [ "f2fs" "vfat" "xfs" ]; + tmp.cleanOnBoot = false; }; nixpkgs.overlays = [ diff --git a/overlays/0001-Remove-relative-config-lookups.patch b/overlays/0001-Remove-relative-config-lookups.patch new file mode 100644 index 0000000..61a6e92 --- /dev/null +++ b/overlays/0001-Remove-relative-config-lookups.patch @@ -0,0 +1,142 @@ +From 57128bb78f56cadf9e2dcca5ba4d710c3bd478a7 Mon Sep 17 00:00:00 2001 +From: Jordan Holt +Date: Mon, 5 Aug 2024 21:53:09 +0100 +Subject: [PATCH] Remove relative config lookups + +--- + src/libcamera/ipa_manager.cpp | 16 ---------- + src/libcamera/ipa_proxy.cpp | 48 ++---------------------------- + src/libcamera/pipeline_handler.cpp | 21 ++----------- + 3 files changed, 4 insertions(+), 81 deletions(-) + +diff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp +index f4e0b633..6d5bbd05 100644 +--- a/src/libcamera/ipa_manager.cpp ++++ b/src/libcamera/ipa_manager.cpp +@@ -131,22 +131,6 @@ IPAManager::IPAManager() + << "No IPA found in '" << modulePaths << "'"; + } + +- /* +- * When libcamera is used before it is installed, load IPAs from the +- * same build directory as the libcamera library itself. +- */ +- std::string root = utils::libcameraBuildPath(); +- if (!root.empty()) { +- std::string ipaBuildPath = root + "src/ipa"; +- constexpr int maxDepth = 2; +- +- LOG(IPAManager, Info) +- << "libcamera is not installed. Adding '" +- << ipaBuildPath << "' to the IPA search path"; +- +- ipaCount += addDir(ipaBuildPath.c_str(), maxDepth); +- } +- + /* Finally try to load IPAs from the installed system path. */ + ipaCount += addDir(IPA_MODULE_DIR); + +diff --git a/src/libcamera/ipa_proxy.cpp b/src/libcamera/ipa_proxy.cpp +index 69975d8f..cd9284a3 100644 +--- a/src/libcamera/ipa_proxy.cpp ++++ b/src/libcamera/ipa_proxy.cpp +@@ -122,33 +122,11 @@ std::string IPAProxy::configurationFile(const std::string &name, + } + } + +- std::string root = utils::libcameraSourcePath(); +- if (!root.empty()) { +- /* +- * When libcamera is used before it is installed, load +- * configuration files from the source directory. The +- * configuration files are then located in the 'data' +- * subdirectory of the corresponding IPA module. +- */ +- std::string ipaConfDir = root + "src/ipa/" + ipaName + "/data"; +- +- LOG(IPAProxy, Info) +- << "libcamera is not installed. Loading IPA configuration from '" +- << ipaConfDir << "'"; +- +- std::string confPath = ipaConfDir + "/" + name; ++ for (const auto &dir : utils::split(IPA_CONFIG_DIR, ":")) { ++ std::string confPath = dir + "/" + ipaName + "/" + name; + ret = stat(confPath.c_str(), &statbuf); + if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG) + return confPath; +- +- } else { +- /* Else look in the system locations. */ +- for (const auto &dir : utils::split(IPA_CONFIG_DIR, ":")) { +- std::string confPath = dir + "/" + ipaName + "/" + name; +- ret = stat(confPath.c_str(), &statbuf); +- if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG) +- return confPath; +- } + } + + if (fallbackName.empty()) { +@@ -197,28 +175,6 @@ std::string IPAProxy::resolvePath(const std::string &file) const + } + } + +- /* +- * When libcamera is used before it is installed, load proxy workers +- * from the same build directory as the libcamera directory itself. +- * This requires identifying the path of the libcamera.so, and +- * referencing a relative path for the proxy workers from that point. +- */ +- std::string root = utils::libcameraBuildPath(); +- if (!root.empty()) { +- std::string ipaProxyDir = root + "src/libcamera/proxy/worker"; +- +- LOG(IPAProxy, Info) +- << "libcamera is not installed. Loading proxy workers from '" +- << ipaProxyDir << "'"; +- +- std::string proxyPath = ipaProxyDir + proxyFile; +- if (!access(proxyPath.c_str(), X_OK)) +- return proxyPath; +- +- return std::string(); +- } +- +- /* Else try finding the exec target from the install directory. */ + std::string proxyPath = std::string(IPA_PROXY_DIR) + proxyFile; + if (!access(proxyPath.c_str(), X_OK)) + return proxyPath; +diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp +index 5ea2ca78..fd8555ca 100644 +--- a/src/libcamera/pipeline_handler.cpp ++++ b/src/libcamera/pipeline_handler.cpp +@@ -561,25 +561,8 @@ std::string PipelineHandler::configurationFile(const std::string &subdir, + struct stat statbuf; + int ret; + +- std::string root = utils::libcameraSourcePath(); +- if (!root.empty()) { +- /* +- * When libcamera is used before it is installed, load +- * configuration files from the source directory. The +- * configuration files are then located in the 'data' +- * subdirectory of the corresponding pipeline handler. +- */ +- std::string confDir = root + "src/libcamera/pipeline/"; +- confPath = confDir + subdir + "/data/" + name; +- +- LOG(Pipeline, Info) +- << "libcamera is not installed. Loading platform configuration file from '" +- << confPath << "'"; +- } else { +- /* Else look in the system locations. */ +- confPath = std::string(LIBCAMERA_DATA_DIR) +- + "/pipeline/" + subdir + '/' + name; +- } ++ confPath = std::string(LIBCAMERA_DATA_DIR) ++ + "/pipeline/" + subdir + '/' + name; + + ret = stat(confPath.c_str(), &statbuf); + if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG) +-- +2.44.1 + diff --git a/overlays/libcamera.nix b/overlays/libcamera.nix new file mode 100644 index 0000000..cdbb7ec --- /dev/null +++ b/overlays/libcamera.nix @@ -0,0 +1,25 @@ +final: prev: +{ + libcamera = prev.libcamera.overrideAttrs (old: { + postPatch = '' + patchShebangs utils/ src/py/ + ''; + + patches = [ + ./0001-Remove-relative-config-lookups.patch + ]; + + mesonFlags = old.mesonFlags ++ [ + "--buildtype=release" + "-Dpipelines=rpi/vc4" + "-Dipas=rpi/vc4" + "-Dgstreamer=enabled" + "-Dtest=false" + "-Dcam=enabled" + ]; + }); + + camera-streamer = prev.callPackage ../pkgs/camera-streamer/package.nix { + libcamera = final.libcamera; + }; +} diff --git a/pkgs/camera-streamer/package.nix b/pkgs/camera-streamer/package.nix index c051f9f..c2bf2f5 100644 --- a/pkgs/camera-streamer/package.nix +++ b/pkgs/camera-streamer/package.nix @@ -1,5 +1,5 @@ { stdenv -, fetchFromGitHub +, fetchFromGitea , cmake , gnumake @@ -12,9 +12,9 @@ , ffmpeg , libcameraSupport ? true , libcamera -, rtspSupport ? true +, rtspSupport ? false , live555 -, webrtcSupport ? true +, webrtcSupport ? false , openssl , lib @@ -24,11 +24,12 @@ stdenv.mkDerivation (finalAttrs: { pname = "camera-streamer"; version = "0.2.8"; - src = fetchFromGitHub { - owner = "ayufan"; + src = fetchFromGitea { + domain = "git.vimium.com"; + owner = "jordan"; repo = "camera-streamer"; - rev = "refs/tags/v${finalAttrs.version}"; - hash = "sha256-8vV8BMFoDeh22I1/qxk6zttJROaD/lrThBxXHZSPpT4="; + rev = "464f05172c725b4b302464eecdb8b6e85fda6e84"; + hash = "sha256-IkLR/oozYU+hfpct+GXej2T3GEhauQtqwWOcrQAErbM="; fetchSubmodules = true; };