From 07cbea642a91bef2e3104d90e42a19c197adeef2 Mon Sep 17 00:00:00 2001 From: "Justin F. Hallett" Date: Wed, 14 Jun 2023 19:03:30 -0600 Subject: [PATCH 1/4] Convert stack to allow for multiple libcamera devices - Rename scripts to a more generic naming - Add libcamera support to scripts, config and systemd - Create a libcamera-default.conf based on libcamera.conf to not brake anything --- ...{libcamera.conf => libcamera-default.conf} | 7 +- scripts/add-camera | 158 ++++++++++++++++++ scripts/add-usb-camera | 98 ----------- scripts/{list-usb-cameras => list-cameras} | 4 + scripts/remove-camera | 35 ++++ scripts/remove-usb-camera | 27 --- ...ice => camera-streamer-libcamera@.service} | 13 +- 7 files changed, 208 insertions(+), 134 deletions(-) rename configs/{libcamera.conf => libcamera-default.conf} (79%) create mode 100644 scripts/add-camera delete mode 100644 scripts/add-usb-camera rename scripts/{list-usb-cameras => list-cameras} (79%) create mode 100644 scripts/remove-camera delete mode 100644 scripts/remove-usb-camera rename systemd/{camera-streamer-libcamera.service => camera-streamer-libcamera@.service} (66%) diff --git a/configs/libcamera.conf b/configs/libcamera-default.conf similarity index 79% rename from configs/libcamera.conf rename to configs/libcamera-default.conf index 2130940..60443bf 100644 --- a/configs/libcamera.conf +++ b/configs/libcamera-default.conf @@ -1,10 +1,11 @@ ### Options for libcamera based cameras (PiCam, Arducam, ...) -# The port on which the webcam server for the camera should listen on. If you have only -# one camera, leave at 8080. If you have more, change to 8081, 8082, etc. The primary -# camera will be considered the one with 8080. +# The port on which the webcam server for the camera should listen on. PORT=8080 +# The path to the camera device. +DEVICE=/base/soc/i2c0mux/i2c@1/imx708@1a + # The resolution to request on the camera sensor. Defaults to 1280x720. WIDTH=1920 HEIGHT=1080 diff --git a/scripts/add-camera b/scripts/add-camera new file mode 100644 index 0000000..836ea60 --- /dev/null +++ b/scripts/add-camera @@ -0,0 +1,158 @@ +#!/bin/bash + +if [ "$EUID" -ne 0 ] + then echo "Please run as root/with sudo" + exit 1 +fi + +if [[ "$1" != "libcamera" ]] && [[ "$1" != "usb" ]] + then echo "type must be libcamera or usb" + exit 1 +fi + +TYPE=$1 +NAME=$2 +PORT=$3 +DEVICE=$4 + +CONFIG_DIR=/etc/camera-streamer.conf.d +CONTROL=/usr/bin/camera-streamer-control + +## Name + +if [ -z "$NAME" ]; then + echo "Usage: $0 [port] [device]" + exit 1 +fi + +# make sure the name is unique +if [ -e "$CONFIG_DIR/$TYPE-$NAME.conf" ]; then + echo "Camera $TYPE-$NAME already exists" + exit 1 +fi + +## Port + +if [ -z "$PORT" ]; then + port=8080 + while grep -qs "PORT=$port" $CONFIG_DIR/*.conf; do + port=$((port+1)) + done + PORT=$port + echo "No port provided, automatically selected port $PORT" + echo +fi + +# make sure the port is available +if grep -qs "PORT=$PORT" $CONFIG_DIR/*.conf; then + echo "Port $PORT is already used by another camera" + exit 1 +fi + +# Get a list all camera for a type +if [[ "$TYPE" == "usb" ]] +then + LIST=$(echo /dev/v4l/by-id/usb-*-video-index0) +else + LIST=$(/usr/bin/libcamera-hello --list-cameras | grep -o '/base/soc/[^)]*') +fi + +## Device + +if [ -z "$DEVICE" ]; then + echo "Please make sure your $TYPE camera is plugged in and select it below:" + echo + PS3="? " + options=($LIST) + select opt in "${options[@]}"; do + if [ -n "$opt" ]; then + DEVICE=$opt + break + fi + echo + done + echo +fi + +# make sure the device exists +if [[ $TYPE == "usb" ]]; then + if [ ! -e "$DEVICE" ]; then + echo "Device $DEVICE does not exist" + exit 1 + fi +else + found=0 + for opt in $LIST; do + if [[ "$opt" == "$DEVICE" ]]; then + found=1 + break + fi + done + if [ $found -eq 0 ]; then + echo "Device $DEVICE does not exist" + exit 1 + fi +fi + +make_usb_conf() { + cat > $CONFIG_DIR/usb-$NAME.conf < $CONFIG_DIR/libcamera-$NAME.conf < " - exit 1 -fi - -# make sure the name is unique -if [ -e "$CONFIG_DIR/usb-$NAME.conf" ]; then - echo "Camera $NAME already exists" - exit 1 -fi - -## Port - -if [ -z "$PORT" ]; then - port=8080 - while grep -qs "PORT=$port" $CONFIG_DIR/*.conf; do - port=$((port+1)) - done - PORT=$port - echo "No port provided, automatically selected port $PORT" - echo -fi - -# make sure the port is available -if grep -qs "PORT=$PORT" $CONFIG_DIR/*.conf; then - echo "Port $PORT is already used by another camera" - exit 1 -fi - -## Device - -if [ -z "$DEVICE" ]; then - echo "Please make sure your USB camera is plugged in and select it below:" - echo - PS3="? " - options=($(echo /dev/v4l/by-id/usb-*-video-index0)) # list all the USB v4l2 devices - select opt in "${options[@]}"; do - if [ -n "$opt" ]; then - DEVICE=$opt - break - fi - echo - done - echo -fi - -# make sure the device exists -if [ ! -e "$DEVICE" ]; then - echo "Device $DEVICE does not exist" - exit 1 -fi - -cat > $CONFIG_DIR/usb-$NAME.conf <" + exit 1 +fi + +if [ ! -e "$CONFIG_DIR/$TYPE-$NAME.conf" ]; then + echo "Camera $TYPE-$NAME does not exist" + exit 1 +fi + +$CONTROL stop $NAME + +rm $CONFIG_DIR/$TYPE-$NAME.conf +if [[ "$TYPE" == "usb" ]]; then + rm /run/systemd/system/camera-streamer-usb-$NAME.path || true +fi +systemctl daemon-reload diff --git a/scripts/remove-usb-camera b/scripts/remove-usb-camera deleted file mode 100644 index 8e3e9a9..0000000 --- a/scripts/remove-usb-camera +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -if [ "$EUID" -ne 0 ] - then echo "Please run as root/with sudo" - exit 1 -fi - -NAME=$1 - -CONFIG_DIR=/etc/camera-streamer.conf.d -CONTROL=/usr/bin/camera-streamer-control - -if [ -z "$NAME" ]; then - echo "Usage: $0 " - exit 1 -fi - -if [ ! -e "$CONFIG_DIR/usb-$NAME.conf" ]; then - echo "Camera $NAME does not exist" - exit 1 -fi - -$CONTROL stop $NAME - -rm $CONFIG_DIR/usb-$NAME.conf -rm /run/systemd/system/camera-streamer-usb-$NAME.path || true -systemctl daemon-reload diff --git a/systemd/camera-streamer-libcamera.service b/systemd/camera-streamer-libcamera@.service similarity index 66% rename from systemd/camera-streamer-libcamera.service rename to systemd/camera-streamer-libcamera@.service index d1f8de8..f6cd7de 100644 --- a/systemd/camera-streamer-libcamera.service +++ b/systemd/camera-streamer-libcamera@.service @@ -1,19 +1,20 @@ [Unit] -Description=camera-streamer libcamera +Description=camera-streamer %i After=network.target +ConditionPathExists=/etc/camera-streamer.conf.d/libcamera-%i.conf StartLimitIntervalSec=120 StartLimitBurst=10 [Service] -EnvironmentFile=/etc/camera-streamer.conf.d/libcamera.conf -ExecCondition=/bin/sh -c "/usr/bin/libcamera-hello --list-cameras | grep -o '/base/soc/[^)]*'" +EnvironmentFile=/etc/camera-streamer.conf.d/libcamera-%i.conf +ExecCondition=/bin/sh -c "/usr/bin/libcamera-hello --list-cameras | grep -o '${DEVICE}'" ExecCondition=/bin/sh -c "! ss -ltn src :$PORT | grep -q LISTEN" -ExecStart=/bin/sh -c "exec /usr/bin/camera-streamer \ +ExecStart=/bin/sh -c "exec /usr/local/bin/camera-streamer \ --http-port=${PORT} \ --camera-type=libcamera \ - --camera-path=$(/usr/bin/libcamera-hello --list-cameras | grep -o '/base/soc/[^)]*' | head -n1) \ + --camera-path=${DEVICE} \ --camera-format=YUYV \ - --camera-width=${WIDTH} --camera-height=${HEIGHT} \ + --camera-width=${WIDTH} -camera-height=${HEIGHT} \ --camera-video.height=${VIDEO_HEIGHT} \ --camera-snapshot.height=${SNAPSHOT_HEIGHT} \ --camera-fps=${FRAMERATE} \ From cfa8c6d12f060d59a5b24bd0e9ec25ac647576af Mon Sep 17 00:00:00 2001 From: "Justin F. Hallett" Date: Wed, 14 Jun 2023 20:34:26 -0600 Subject: [PATCH 2/4] Fix for #1, display none if there are none --- scripts/list-cameras | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/list-cameras b/scripts/list-cameras index 9a1657a..fc0c8c1 100644 --- a/scripts/list-cameras +++ b/scripts/list-cameras @@ -10,10 +10,14 @@ for path in /dev/v4l/by-id/usb-*-video-index0; do echo v4l2-ctl --device "$path" --all --list-formats --list-formats-ext else - echo " $path" + echo " None available" fi done echo echo "Available libcamera devices:" -/usr/bin/libcamera-hello --list-cameras +if [ -e /usr/bin/libcamera-hello ]; then + /usr/bin/libcamera-hello --list-cameras +else + echo " None available" +fi From f4670787b6c249b9cfb55d6ffe11fe531688a8de Mon Sep 17 00:00:00 2001 From: "Justin F. Hallett" Date: Thu, 15 Jun 2023 08:32:31 -0600 Subject: [PATCH 3/4] Cleaner output, also indicates if there is already a config for each libcamera --- scripts/list-cameras | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/list-cameras b/scripts/list-cameras index fc0c8c1..bcb7a32 100644 --- a/scripts/list-cameras +++ b/scripts/list-cameras @@ -2,6 +2,8 @@ ALL=$1 +CONFIG_DIR=/etc/camera-streamer.conf.d + echo "Available USB camera devices:" for path in /dev/v4l/by-id/usb-*-video-index0; do if [[ "$ALL" == "--all" ]]; then @@ -14,10 +16,21 @@ for path in /dev/v4l/by-id/usb-*-video-index0; do fi done + echo -echo "Available libcamera devices:" +echo "Available libcamera devices (* = in a config):" if [ -e /usr/bin/libcamera-hello ]; then - /usr/bin/libcamera-hello --list-cameras + IFS=$'\n' + LIST=$(/usr/bin/libcamera-hello --list-cameras | grep -v '^ ' | sed -e '1,2d') + for d in $LIST; do + inuse=' ' + device=$(echo $d | grep -o '/base/soc/[^)]*') + if grep -qs "DEVICE=$device" $CONFIG_DIR/*.conf; then + inuse='*' + fi + echo " [$inuse] $d" + done + unset IFS else echo " None available" fi From 0fea3c2f258a20ba6580607e3c101b92d494fd7a Mon Sep 17 00:00:00 2001 From: "Justin F. Hallett" Date: Thu, 15 Jun 2023 08:35:39 -0600 Subject: [PATCH 4/4] Check if the device already has a config --- scripts/add-camera | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/add-camera b/scripts/add-camera index 836ea60..3d81b2c 100644 --- a/scripts/add-camera +++ b/scripts/add-camera @@ -94,6 +94,11 @@ else fi fi +if grep -qs "DEVICE=$DEVICE" $CONFIG_DIR/*.conf; then + echo "Device $DEVICE is already configured" + exit 1 +fi + make_usb_conf() { cat > $CONFIG_DIR/usb-$NAME.conf <