me like nix
0

Configure Feed

Select the types of activity you want to include in your feed.

1{ ... }: { 2 flake.modules.nixos.pi-camera = 3 { pkgs, lib, config, ... }: 4 let 5 cfg = config.pi; 6 7 deviceTree_overlay = _final: prev: { 8 deviceTree = { 9 applyOverlays = prev.callPackage ../hosts/pi-common/overlays/apply-overlays-dtmerge.nix { }; 10 compileDTS = prev.deviceTree.compileDTS; 11 }; 12 }; 13 14 libcamera-rpi = pkgs.libcamera.overrideAttrs (old: { 15 mesonFlags = (old.mesonFlags or [ ]) ++ [ 16 "-Dipas=rpi/vc4,rpi/pisp" 17 "-Dpipelines=rpi/vc4,rpi/pisp" 18 ]; 19 }); 20 21 rpicam-apps = pkgs.stdenv.mkDerivation rec { 22 pname = "rpicam-apps"; 23 version = "1.11.1"; 24 25 src = pkgs.fetchFromGitHub { 26 owner = "raspberrypi"; 27 repo = "rpicam-apps"; 28 rev = "v${version}"; 29 hash = "sha256-hVoKbvWFeramPkHuibJwUgFOPS9v588+K8828a1fNnA="; 30 }; 31 32 nativeBuildInputs = with pkgs; [ 33 meson 34 ninja 35 pkg-config 36 ]; 37 38 buildInputs = [ 39 libcamera-rpi 40 pkgs.libdrm 41 pkgs.libexif 42 pkgs.libjpeg 43 pkgs.libpng 44 pkgs.libtiff 45 pkgs.boost 46 pkgs.ffmpeg 47 ]; 48 49 mesonFlags = [ 50 "-Denable_libav=enabled" 51 "-Denable_drm=enabled" 52 "-Denable_egl=disabled" 53 "-Denable_qt=disabled" 54 "-Denable_opencv=disabled" 55 "-Denable_tflite=disabled" 56 "-Denable_hailo=disabled" 57 ]; 58 59 meta = with lib; { 60 description = "Raspberry Pi camera applications"; 61 homepage = "https://github.com/raspberrypi/rpicam-apps"; 62 license = licenses.bsd2; 63 platforms = [ "aarch64-linux" ]; 64 }; 65 }; 66 in 67 { 68 options.pi = { 69 streamName = lib.mkOption { 70 type = lib.types.str; 71 description = "Name of the camera stream"; 72 }; 73 resolution = { 74 width = lib.mkOption { 75 type = lib.types.int; 76 default = 1920; 77 description = "Camera resolution width"; 78 }; 79 height = lib.mkOption { 80 type = lib.types.int; 81 default = 1080; 82 description = "Camera resolution height"; 83 }; 84 }; 85 framerate = lib.mkOption { 86 type = lib.types.int; 87 default = 30; 88 description = "Camera framerate"; 89 }; 90 deviceTreeFilter = lib.mkOption { 91 type = lib.types.str; 92 description = "Device tree filter pattern"; 93 }; 94 deviceTreeCompatible = lib.mkOption { 95 type = lib.types.str; 96 description = "Device tree compatible string"; 97 }; 98 gpuMem = lib.mkOption { 99 type = lib.types.int; 100 default = 256; 101 description = "GPU memory allocation in MB"; 102 }; 103 flipCamera = lib.mkOption { 104 type = lib.types.bool; 105 default = false; 106 description = "Flip camera image 180 degrees"; 107 }; 108 }; 109 110 config = { 111 # CMA is configured via device tree overlay (cma-256m) 112 # Do NOT use boot.kernelParams cma= as it bypasses the DT node 113 # and prevents /dev/dma_heap/linux,cma from being created 114 115 nix.settings.trusted-users = [ "sean" ]; 116 117 networking.useDHCP = true; 118 nixpkgs.overlays = [ deviceTree_overlay ]; 119 120 boot.supportedFilesystems = lib.mkForce [ 121 "vfat" 122 "ext4" 123 ]; 124 boot.initrd.systemd.enable = false; 125 126 services.openssh = { 127 enable = true; 128 settings = { 129 PasswordAuthentication = false; 130 PermitRootLogin = "no"; 131 }; 132 }; 133 134 users.users.sean = { 135 isNormalUser = true; 136 extraGroups = [ 137 "wheel" 138 "video" 139 ]; 140 openssh.authorizedKeys.keys = [ 141 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCIqgZ7kedxo+mOW7YG73Vp3zel3h180y3GKvHtRsXfGlpIIvRDy7pgCBQ4AGXYD4y78URQmFohYSAPqCPOPaWcU2un3XG9KvCzEsHmsbskPonitUmCiKvrKkb6oW4jCBtd7AEtBn+AiajAQFtPZ7NN2Df3AmTypvR6Irg7R+nxnfc9NTIHmGvxSDyWcbb4pguL20sctUSqGL6xGh8q/bqhdOThSimM+z9bEUNxK/5rPhwkNniMrp4pJcUrUiAh5/4DiRFG6KT+oeg+/myoz/Z1sPvAs7u/8JDQI4RshRD8Hu0oTkRBN6Hxj478q2SXbeBUZlD6IdjP3RhGpmSecoDdtWqKbpuV3eVRtQtba3KL86GBeV/bugaOdJ1Aud+1SOFJreAAuvxzMMKT+cdQZk6oOPP148DA/No+mDm/2S43lcdCXh79wA6YRAmKQ8jmZxTCtPutrvuZK1rguvvUlEoG/vhdNHh7eDa4Td07V6bjCRPUl8qk/e4M0E3pwsTlZc=" 142 "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIOIgEteUEW06dnBHe2z8vNLwz2iMKe8bba6JgMmOUpcBAAAABHNzaDo= sean@framework16" 143 ]; 144 }; 145 146 security.sudo.wheelNeedsPassword = false; 147 148 services.go2rtc = { 149 enable = true; 150 settings = { 151 ffmpeg.bin = "${pkgs.ffmpeg}/bin/ffmpeg"; 152 streams = { 153 "${cfg.streamName}" = "exec:${rpicam-apps}/bin/rpicam-vid -t 0 --width ${toString cfg.resolution.width} --height ${toString cfg.resolution.height} --framerate ${toString cfg.framerate} --codec h264 --inline --autofocus-mode continuous${lib.optionalString cfg.flipCamera " --vflip --hflip"} -o -"; 154 }; 155 }; 156 }; 157 158 services.udev.extraRules = '' 159 SUBSYSTEM=="dma_heap", GROUP="video", MODE="0660" 160 ''; 161 162 systemd.services.go2rtc.serviceConfig = { 163 User = lib.mkForce "root"; 164 SupplementaryGroups = [ "video" ]; 165 }; 166 systemd.services.go2rtc.environment = { 167 LIBCAMERA_IPA_MODULE_PATH = "${libcamera-rpi}/lib/libcamera/ipa"; 168 }; 169 170 environment.systemPackages = [ 171 pkgs.ffmpeg 172 pkgs.libraspberrypi 173 libcamera-rpi 174 rpicam-apps 175 pkgs.v4l-utils 176 ]; 177 178 hardware.deviceTree.filter = cfg.deviceTreeFilter; 179 hardware.deviceTree.overlays = [ 180 { 181 # Increase CMA from 64MB to 256MB via device tree 182 # (cmdline cma= bypasses the DT node and /dev/dma_heap/linux,cma isn't created) 183 name = "cma-256m"; 184 dtsText = '' 185 /dts-v1/; 186 /plugin/; 187 188 / { 189 compatible = "${cfg.deviceTreeCompatible}"; 190 191 fragment@99 { 192 target-path = "/reserved-memory/linux,cma"; 193 __overlay__ { 194 size = <0x00 0x10000000>; /* 256MB */ 195 }; 196 }; 197 }; 198 ''; 199 } 200 { 201 name = "imx708-overlay"; 202 dtsText = '' 203 // SPDX-License-Identifier: GPL-2.0-only 204 // Definitions for IMX708 camera module on VC I2C bus 205 /dts-v1/; 206 /plugin/; 207 208 /{ 209 compatible = "${cfg.deviceTreeCompatible}"; 210 211 fragment@0 { 212 target = <&i2c0if>; 213 __overlay__ { 214 status = "okay"; 215 }; 216 }; 217 218 clk_frag: fragment@1 { 219 target = <&cam1_clk>; 220 __overlay__ { 221 status = "okay"; 222 clock-frequency = <24000000>; 223 }; 224 }; 225 226 fragment@2 { 227 target = <&i2c0mux>; 228 __overlay__ { 229 status = "okay"; 230 }; 231 }; 232 233 reg_frag: fragment@3 { 234 target = <&cam1_reg>; 235 cam_reg: __overlay__ { 236 startup-delay-us = <70000>; 237 off-on-delay-us = <30000>; 238 regulator-min-microvolt = <2700000>; 239 regulator-max-microvolt = <2700000>; 240 }; 241 }; 242 243 i2c_frag: fragment@100 { 244 target = <&i2c_csi_dsi>; 245 __overlay__ { 246 #address-cells = <1>; 247 #size-cells = <0>; 248 status = "okay"; 249 250 cam_node: imx708@1a { 251 compatible = "sony,imx708"; 252 reg = <0x1a>; 253 status = "okay"; 254 255 clocks = <&cam1_clk>; 256 clock-names = "inclk"; 257 258 vana1-supply = <&cam1_reg>; 259 vana2-supply = <&cam_dummy_reg>; 260 vdig-supply = <&cam_dummy_reg>; 261 vddl-supply = <&cam_dummy_reg>; 262 263 rotation = <180>; 264 orientation = <2>; 265 266 port { 267 cam_endpoint: endpoint { 268 clock-lanes = <0>; 269 data-lanes = <1 2>; 270 clock-noncontinuous; 271 link-frequencies = 272 /bits/ 64 <450000000>; 273 }; 274 }; 275 }; 276 277 vcm_node: dw9817@c { 278 compatible = "dongwoon,dw9817-vcm"; 279 reg = <0x0c>; 280 status = "okay"; 281 VDD-supply = <&cam1_reg>; 282 }; 283 }; 284 }; 285 286 csi_frag: fragment@101 { 287 target = <&csi1>; 288 csi: __overlay__ { 289 status = "okay"; 290 brcm,media-controller; 291 292 port { 293 csi_ep: endpoint { 294 remote-endpoint = <&cam_endpoint>; 295 clock-lanes = <0>; 296 data-lanes = <1 2>; 297 clock-noncontinuous; 298 }; 299 }; 300 }; 301 }; 302 303 __overrides__ { 304 rotation = <&cam_node>,"rotation:0"; 305 orientation = <&cam_node>,"orientation:0"; 306 media-controller = <&csi>,"brcm,media-controller?"; 307 cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, 308 <&csi_frag>, "target:0=",<&csi0>, 309 <&clk_frag>, "target:0=",<&cam0_clk>, 310 <&reg_frag>, "target:0=",<&cam0_reg>, 311 <&cam_node>, "clocks:0=",<&cam0_clk>, 312 <&cam_node>, "vana1-supply:0=",<&cam0_reg>, 313 <&vcm_node>, "VDD-supply:0=",<&cam0_reg>; 314 vcm = <&vcm_node>, "status", 315 <0>, "=4"; 316 link-frequency = <&cam_endpoint>,"link-frequencies#0"; 317 }; 318 }; 319 320 &cam_endpoint { 321 remote-endpoint = <&csi_ep>; 322 }; 323 ''; 324 } 325 ]; 326 327 hardware.enableRedistributableFirmware = true; 328 329 sdImage.populateFirmwareCommands = lib.mkAfter '' 330 chmod u+w ./firmware/config.txt 331 cat >> ./firmware/config.txt << EOF 332 333 # Camera support - Pi Camera v3 (IMX708) 334 gpu_mem=${toString cfg.gpuMem} 335 EOF 336 337 if [ -d ${pkgs.raspberrypifw}/share/raspberrypi/boot/overlays ]; then 338 cp -r ${pkgs.raspberrypifw}/share/raspberrypi/boot/overlays ./firmware/ 339 fi 340 ''; 341 342 networking.firewall.allowedTCPPorts = [ 343 22 344 1984 345 8554 346 ]; 347 }; 348 }; 349}