From d6c791531b99261b49a76ced98905f238b6bde08 Mon Sep 17 00:00:00 2001 From: Anonymousdog <30508073+Anonymousdog@users.noreply.github.com> Date: Sat, 2 Jun 2018 02:29:10 -0400 Subject: [PATCH] 0.8.3 --- README | 75 ++++++ black.png | Bin 0 -> 1637 bytes displaycameras | 327 +++++++++++++++++++++++++ displaycameras.conf | 41 ++++ displaycameras.service | 28 +++ example_layouts/layout.1440x900.3x3 | 95 +++++++ example_layouts/layout.1920x1080.3x3 | 98 ++++++++ example_layouts/layout.conf.1280x1028 | 73 ++++++ example_layouts/layout.conf.1280x720 | 67 +++++ example_layouts/layout.conf.1280x768 | 67 +++++ example_layouts/layout.conf.1440x900 | 65 +++++ example_layouts/layout.conf.large_left | 86 +++++++ example_layouts/layout.examples | 197 +++++++++++++++ install.sh | 138 +++++++++++ layout.conf.default | 72 ++++++ omxplayer_dbuscontrol | 86 +++++++ repaircameras.cron | 6 + rotatedisplays | 7 + 18 files changed, 1528 insertions(+) create mode 100644 README create mode 100644 black.png create mode 100644 displaycameras create mode 100644 displaycameras.conf create mode 100644 displaycameras.service create mode 100644 example_layouts/layout.1440x900.3x3 create mode 100644 example_layouts/layout.1920x1080.3x3 create mode 100644 example_layouts/layout.conf.1280x1028 create mode 100644 example_layouts/layout.conf.1280x720 create mode 100644 example_layouts/layout.conf.1280x768 create mode 100644 example_layouts/layout.conf.1440x900 create mode 100644 example_layouts/layout.conf.large_left create mode 100644 example_layouts/layout.examples create mode 100644 install.sh create mode 100644 layout.conf.default create mode 100644 omxplayer_dbuscontrol create mode 100644 repaircameras.cron create mode 100644 rotatedisplays diff --git a/README b/README new file mode 100644 index 0000000..7902572 --- /dev/null +++ b/README @@ -0,0 +1,75 @@ +Systemd init system (because Raspbian) is presumed. +If installing on 'nix with other init systems, you will have to edit the install script or enable the displaycameras service with available tools for your init system. +The main script, normally installed at /usr/bin/displaycameras has an LSB header and will run as a systemv init script (if copied to /etc/init.d/). +Maybe just symlink to the /usr/bin/ location (untested)? No other init systems have been tested. + +## Installation ## +run 'sudo install.sh' +Accept the offer to view the README after successful installation and follow the instructions therein + +## Upgrade ## +run 'sudo install.sh upgrade' +No changes will be made to your existing config files, cron job setup, gpu memory allocation, or hdmi overscan setup. + +## Removal ## +1. Stop the service 'sudo systemctl stop displaycameras.service' +2. Disable the service 'sudo systemctl disable displaycameras.service' +3. Remove the files: + a. Remove the config directory, 'sudo rm -R /etc/displaycameras' + b. Remove the service file, 'sudo rm /etc/systemd/system/displaycameras.service' + c. Remove the scripts, 'sudo rm /usr/bin/omxplayer_dbuscontrol /usr/bin/black.png /usr/bin/rotatedisplays' + d. Remove the crontab file, 'sudo rm /etc/cron.d/repaircameras && sudo systemctl restart cron' +4. Remove the pre-requisites (optional), 'for each package in omxplayer fbi; do sudo apt-get purge $package -y; done' +5. Remove pre-requisites' dependencies (optional), 'sudo apt-get autoremove -y' + +## Post Instalation Instruction ## +==== CONFIGURATION ====" +Remember to edit the /etc/displaycameras/displaycameras.conf and /etc/displaycameras/layout.conf.default files for your environment. + +==== Minimal Configuration ==== + +=== Global Options === +== Main Conf File == +Global options like screen blanking, omxplayer network timeout, startsleep, feedsleep, retry, displaydetect, and rotatedelay in /etc/displaycameras/displaycameras.conf. +All of these variables may be added to one or more layout configuration files to override the global options settings for one or more display layouts. + +=== Camera and Window Layout === +Screen/window matrix setup, window names, camera names, and camera feeds should be here (and most definitely NOT in the main config file). +Global options (exept for displaydetect) in the main conf file may be overridden (for specific displays) by supplying their values in these files. +Do NOT override 'displaydetect' settings in a layout config file; you will create problems. +== Layout Conf Files == +All files in /etc/displaycameras/ which follow the naming convention 'layout.conf.' or the default layout conf file, layout.conf.default. +Unless you enable display detection in the main config file, the system will always use the default layout conf file. +== Default Layout Config File == +The default layout file now has rotation disabled by default; so, it's safe to throw your camera names and feeds in there and just use it if you want an onscreen 2x2 matrix on reliably 1080p displays. If you have more than four cameras, you'll want to uncomment the last line. + +==== Advanced Configurations ==== +Perform all the steps in the minimal configuration and review the following options for tweaks to your setup. +== Display Detection == +Enable display detection in displaycameras.conf and setup special layout configuration files for any display resolutions you want to support with auto-detection. Use the 1440x900 or 1280x1028 (and other) files as examples, and +duplicate the naming convention for these configuration file names, '/etc/displaycameras/layout.conf.' (e.g., /etc/displaycameras/layout.conf.1024x768). <--No, a 1024x768 layout +config file is not included in this package. + +== Rotation == +If you want to display more cameras on screen than the screen will hold, ensure you have at least as many windows defined as cameras, and uncomment the 'rotate="true"' line in the main config file (for all displays) or in a +custom layout file (for a specific screen resolution). + +== Display Blanking == +If your display shows background items from the terminal or GUI screen during rotation, you may want to enable screen "blanking" by uncommenting or adding a 'blank="true"' line in the main (for all displays) or custom layout files. + +== Proper feed resolutions == +!!!WARNING!!! +Configure camera feeds that are the same resolution or SMALLER than your windows. The RPi will struggle to downscale feeds to smaller windows. + +== Boot Config Changes == +You may want to adjust the gpu_mem value in /boot/config.txt if gpu resources restrict performance. + +Installation ensures there is a "disable_overscan=1" line in your /boot/config.txt +file. This disables overscan compensation which allows display resolutions +autodetection to work properly. We recommend you setup your monitor to disable overscan. +It is often enabled by default on televisions and some commercial displays. + +==== TESTING ==== +Test by starting the service manually, "sudo /usr/bin/displaycameras start", to see the full output of the script. In the main config file, /etc/displaycameras/displaycameras.conf, adjust feedsleep upward until you no longer see script output reflecting omxplayer playback (not startup) +retries. Once that is resolved, adjust startsleep upward until you no longer see script output reflecting omxplayer startup or playback retries. Increase retries if results are inconsistent but you want short startup or +feedsleep values (for quicker startup). diff --git a/black.png b/black.png new file mode 100644 index 0000000000000000000000000000000000000000..3dc95fab0072968d408eea6098b4bb37dcc99442 GIT binary patch literal 1637 zcmeAS@N?(olHy`uVBq!ia0y~yU_QXWz$C-L1Qgk3AD{!I7>k44ofy`glX(f`u%tWs zIx;Y9?C1WI$O`0h7I;J!GcX91fH32|H2De!2G(DmE{-7;ac>VYG6Iz}Dg0lb=ivZk pje^k-7!85Z5Eu=C;TZyRRx|D^WnkQP;6((;gPyK_F6*2UngCaSA$I@( literal 0 HcmV?d00001 diff --git a/displaycameras b/displaycameras new file mode 100644 index 0000000..fdf8055 --- /dev/null +++ b/displaycameras @@ -0,0 +1,327 @@ +#!/bin/bash +### BEGIN INIT INFO +# Provides: omxplayer +# Required-Start: $network $local_fs dbus cron +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Displays camera feeds for monitoring +# Description: +### END INIT INFO + +#version:0.8.3 + +# Exit if not root +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root" + exit 0 +fi + +# Exit if omxplayer_dbus is not executable and in the PATH +if [ ! `which omxplayer_dbuscontrol` ]; then + echo "omxplayer_dbuscontrol must be executable and in the PATH env variable." + exit 1 +fi + +# Exit if omxplayer is not installed +if [ ! `which omxplayer` ]; then + echo "Please, install omxplayer." + exit 1 +fi + +# Exit if config file is not present and readable +if [ -r /etc/displaycameras/displaycameras.conf ]; then + . /etc/displaycameras/displaycameras.conf; +else + echo "/etc/displaycameras/displaycameras.conf does not exist or is not readable." + exit 1 +fi + +# Exit if default layout config file is not present and readable +if [ ! -r /etc/displaycameras/layout.conf.default ]; then + echo "/etc/displaycameras/layout.conf.default does not exist or is not readable." + exit 1 +fi + +# If enabled, autodetect display mode, check for layout config file for that +# mode, and load that file if present. +if [ "$displaydetect" = "true" ]; then + if [ "`grep disable_overscan /boot/config.txt | egrep -v ^#`" = "disable_overscan=1" ]; then + mode="`fbset -s | egrep ^mode | awk -v N=2 '{print $2}'`" + # remove quotes surrounding $mode + mode=${mode%\"} + mode=${mode#\"} + if [ -r /etc/displaycameras/layout.conf.$mode ]; then + . /etc/displaycameras/layout.conf.$mode + displaydetectactive=true + else + . /etc/displaycameras/layout.conf.default + echo "No layout configuration file found for $mode resolution." + fi + else + . /etc/displaycameras/layout.conf.default + echo "Display resolution autodetection will not work properly with overscan enabled." + echo "Ensure disable_overscan=1 is in /boot/config.txt." + fi +else + . /etc/displaycameras/layout.conf.default +fi + +# Ensure there is an omxplayer timeout value +if [ "$omx_timeout" = "" ]; then + omx_timeout=30 +fi + +# Set a variables for PID file and Display Sequence file +PIDFILE=/var/run/displaycameras.pid +DISPLAY_SEQUENCE_FILE=/tmp/displaycameras.seq + +# How many cameras do we have? +cameras="${#camera_names[@]}" +# Set the max camera rotation sequence as one less than the number of cameras +# (since it starts at zero). +max_seq=$((cameras-1)) + +# Figure out the current display sequence or set it to zero if it doesn't exist. +if [ ! -f $DISPLAY_SEQUENCE_FILE ]; then + echo 0 > $DISPLAY_SEQUENCE_FILE +fi +declare -i DISPLAY_SEQUENCE +DISPLAY_SEQUENCE=`cat $DISPLAY_SEQUENCE_FILE` + +#Functions + +case "$1" in +# Start displaying camera feeds +start) +if [ -f $PIDFILE ]; then + echo "PID file exists! Stop or Restart this service instead." +exit 1 +fi +if [ "$blank" = "true" ]; then + echo "Blanking screen" + fbi --noverbose -T 2 /usr/bin/black.png >/dev/null 2>&1 & +fi +if [ "$displaydetectactive" = "true" ]; then + echo "Display detection is active for $mode resolution." +fi +startupfailure=false +feedfailure=false +for i in ${!camera_names[*]} +do + startupretry=0 + feedretry=0 + x=$((i+$DISPLAY_SEQUENCE)) + if [ "$x" -ge "${#camera_names[@]}" ]; then x=$((x-${#camera_names[@]})) + fi + player="omxplayer --no-keys --no-osd --avdict rtsp_transport:tcp --win \"${window_positions[$x]}\" \"${camera_feeds[$i]}\" --live -n -1 --timeout "$omx_timeout" --dbus_name "org.mpris.MediaPlayer2.omxplayer.${camera_names[$i]}" >/dev/null &" + echo "Starting omxplayer for ${camera_names[$i]}" + eval $player + sleep $startsleep + while [ "`omxplayer_dbuscontrol ${camera_names[$i]} getplaystatus`" != "Playing" ] + do + sleep 1 + echo "Waiting for ${camera_names[$i]} omxplayer startup $startupretry" + if [ "$startupretry" -eq "$retry" ]; then + break + fi + startupretry=$((startupretry+1)) + done + if [ "`omxplayer_dbuscontrol ${camera_names[$i]} getplaystatus`" = "Playing" ] + then + sleep $feedsleep + while [ "`omxplayer_dbuscontrol ${camera_names[$i]} getposition`" = "0s" ] + do + sleep 1 + echo "Waiting for ${camera_names[$i]} playback $feedretry" + if [ "$feedretry" -eq "$retry" ]; then + omxplayer_dbuscontrol $i quit + feedfailure=true + break + fi + feedretry=$((feedretry+1)) + done + else + startupfailure=true + fi + if [ "`omxplayer_dbuscontrol ${camera_names[$i]} getplaystatus`" = "Playing" ] && [ "`omxplayer_dbuscontrol ${camera_names[$i]} getposition`" != "0s" ]; then + echo "${camera_names[$i]} started" + else + echo "${camera_names[$i]} failed playback" + fi +done +touch $PIDFILE +# One go at a repair job if not all displays start correctly +if [ "$startupfailure" = "true" ] || [ "$feedfailure" = "true" ]; then + echo "Running a repair on failed feeds." + $0 repair startup +fi +echo "Camera Display Started" +echo "For complete status info, run" +echo "/usr/bin/displaycameras status." +if [ "$rotate" = "true" ]; then + if [ "$rotatedelay" = "" ]; then + rotatedelay=5 + fi + echo "Starting camera rotation" + rotatedisplays $rotatedelay & +fi +;; + +# Stop displaying camera feeds +stop) +rm -f $PIDFILE +rm -f $DISPLAY_SEQUENCE_FILE +if [ "$rotate" = "true" ]; then + pkill rotatedisplays +fi +for i in ${camera_names[@]} +do + omxplayer_dbuscontrol $i quit +done +sleep 2 +if [ "$blank" = "true" ]; then + pkill fbi +fi +killall omxplayer.bin > /dev/null 2>&1 +echo "Camera Display Stopped" +exit 0 +;; + +# Restart +restart) +$0 stop +sleep 1 +$0 start +;; + +# Restart any camera feeds that don't claim to be playing or restart the service +# if too many omxplayer.bin instances are active. +repair) +# Do nothing unless the service PID file exists +if [ ! -f $PIDFILE ]; then exit 0; fi +# Stop and start the service if we have too many omxplayers +if [ `pgrep -c omxplayer.bin` -gt $cameras ] +then + $0 restart +fi +# The actual repair part +for i in ${!camera_names[*]} +do + if [ "`omxplayer_dbuscontrol ${camera_names[$i]} getplaystatus`" != "Playing" -o "`omxplayer_dbuscontrol ${camera_names[$i]} getposition`" = "0s" ] + then + rm -f $PIDFILE + pkill rotatedisplays + omxplayer_dbuscontrol ${camera_names[$i]} quit + x=$((i+$DISPLAY_SEQUENCE)) + if [ "$x" -ge "${#camera_names[@]}" ]; then x=$((x-${#camera_names[@]})) + fi + player="omxplayer --no-keys --no-osd --avdict rtsp_transport:tcp --win \"${window_positions[$x]}\" \"${camera_feeds[$i]}\" --live -n -1 --timeout "$omx_timeout" --dbus_name "org.mpris.MediaPlayer2.omxplayer.${camera_names[$i]}" >/dev/null &" + echo "Starting omxplayer for ${camera_names[$i]}" + eval $player + sleep $startsleep + startupretry=0 + feedretry=0 + while [ "`omxplayer_dbuscontrol ${camera_names[$i]} getplaystatus`" != "Playing" ] + do + sleep 1 + echo "Waiting for ${camera_names[$i]} omxplayer startup $startupretry" + if [ "$startupretry" -eq "$retry" ]; then + break + fi + startupretry=$((startupretry+1)) + done + if [ "`omxplayer_dbuscontrol ${camera_names[$i]} getplaystatus`" = "Playing" ] + then + sleep $feedsleep + while [ "`omxplayer_dbuscontrol ${camera_names[$i]} getposition`" = "0s" ] + do + sleep 1 + echo "Waiting for ${camera_names[$i]} playback $feedretry" + if [ "$feedretry" -eq "$retry" ]; then + omxplayer_dbuscontrol $i quit + feedfailure=true + break + fi + feedretry=$((feedretry+1)) + done + else + startupfailure=true + fi + if [ "`omxplayer_dbuscontrol ${camera_names[$i]} getplaystatus`" = "Playing" ] && [ "`omxplayer_dbuscontrol ${camera_names[$i]} getposition`" != "0s" ]; then + echo "${camera_names[$i]} started" + else + echo "${camera_names[$i]} failed playback" + fi + touch $PIDFILE + if [ "$rotate" = "true" ]; then + if [ "$rotatedelay" = "" ]; then + rotatedelay=5 + fi + if [ "$2" != "startup" ]; then + echo "Restarting camera rotation" + rotatedisplays $rotatedelay & + fi + fi + fi +done +;; + +rotate) +# Do nothing unless the service PID file exists +if [ ! -f $PIDFILE ]; then exit 0; fi +DISPLAY_SEQUENCE=$((DISPLAY_SEQUENCE-1)) +if [ "$DISPLAY_SEQUENCE" -lt "0" ]; then + DISPLAY_SEQUENCE="$max_seq" +fi +for i in ${!camera_names[*]} +do + y=$((i-DISPLAY_SEQUENCE-1)) + if [ "$y" -lt "0" ]; then y=$((y+"${#camera_names[@]}")) + fi + if [ "$y" -ge "${#camera_names[@]}" ]; then y=$((y-"${#camera_names[@]}" +)) + fi + x=$((y+$DISPLAY_SEQUENCE)) + if [ "$x" -ge "${#camera_names[@]}" ]; then x=$((x-"${#camera_names[@]}" +)) + fi + eval omxplayer_dbuscontrol "${camera_names[$y]}" setvideopos \"${window_positions[$x]}\" +done +echo $DISPLAY_SEQUENCE > $DISPLAY_SEQUENCE_FILE +;; + +rotaterev) +if [ ! -f $PIDFILE ]; then exit 0; fi +DISPLAY_SEQUENCE=$((DISPLAY_SEQUENCE+1)) +if [ "$DISPLAY_SEQUENCE" -ge "${#camera_names[@]}" ]; then + DISPLAY_SEQUENCE=0 +fi +for i in ${!camera_names[*]} +do + y=$((i-DISPLAY_SEQUENCE+1)) + if [ "$y" -lt "0" ]; then y=$((y+"${#camera_names[@]}")) + fi + if [ "$y" -ge "${#camera_names[@]}" ]; then y=$((y-"${#camera_names[@]}")) + fi + x=$((y+$DISPLAY_SEQUENCE)) + if [ "$x" -ge "${#camera_names[@]}" ]; then x=$((x-"${#camera_names[@]}")) + fi + eval omxplayer_dbuscontrol "${camera_names[$y]}" setvideopos \"${window_positions[$x]}\" +done +echo $DISPLAY_SEQUENCE > $DISPLAY_SEQUENCE_FILE +;; + +positions) +for i in "${camera_names[@]}" +do + position="`omxplayer_dbuscontrol $i getposition`" + echo "$position $i" +done +;; + +*) +echo "Usage: /usr/bin/displaycameras {start|stop|restart|repair|status|positions|echo|rotate|rotaterev}" +exit 1 +;; +esac diff --git a/displaycameras.conf b/displaycameras.conf new file mode 100644 index 0000000..9e8f628 --- /dev/null +++ b/displaycameras.conf @@ -0,0 +1,41 @@ +# This is the configuration file for the displaycameras service intended to +# play a series of camera feeds from Ubiquity camera systems. +# This file sets the global options for the service, but the camera names, +# feeds, display windows, display window names, and rotation are set in the +# display layout files, /etc/displaycameras/layout.conf.default (required) +# and any /etc/displaycameras/layout.conf. you want to support +# when you enable displaydetect in this file. See the commented layout section +# below for examples to use in the layout files. + +#### Global Options + +# Do we need screen blanking before displaying cameras (default false) +# This depends on "fbi" being installed. Blanking fails without it. +#blank="true" + +# Optimize reliability by tweaking omx_timeout and/or sleep factor. + +# omxplayer network timeout (for establishing feed playback) in seconds. +# I recommend this be no less than 15s and that you increase it as you add +# more than six low-res or four mid-res feeds or add network hops or bandwidth +# challenges to playing the feeds. +omx_timeout=30 + +# Amount of sleep time we allow per camera when starting|restarting|repairing. +# Recommend no less than 3s start sleep and 1s feedsleep. You may increase this +# when running higher-res feeds, a large number of cameras, or over slow +# network links. +startsleep=3 +feedsleep=1 +# Retry is how many seconds of sleep that the script waits after the start or feed +# sleep for omxplayer to first report playback, then playback beyond zero seconds. +retry=5 + +# Enable display detection (disabled by default) if you setup layout configuration +# files of the naming convention 'layout.conf.' (e.g. +# layout.conf.1280x1024). These files should include window names, +# window positions, camera names, camera feeds, and rotation configuration. +#displaydetect=true + +# When rotating camera feeds across a display, how many seconds does each rotation last? (default=5) +#rotatedelay=8 \ No newline at end of file diff --git a/displaycameras.service b/displaycameras.service new file mode 100644 index 0000000..6669863 --- /dev/null +++ b/displaycameras.service @@ -0,0 +1,28 @@ +[Unit] +Documentation=man:systemd-sysv-generator(8) +Description=Displays camera feeds for monitoring +Before=multi-user.target +Before=multi-user.target +Before=multi-user.target +Before=graphical.target +After=network-online.target +After=dbus.service +After=cron.service +Wants=network-online.target + +[Service] +Type=oneshot +Restart=no +TimeoutSec=5min +IgnoreSIGPIPE=no +LimitNPROC=1 +KillMode=control-group +GuessMainPID=no +RemainAfterExit=yes +SuccessExitStatus=5 6 +ExecStart=/usr/bin/displaycameras start +ExecStop=/usr/bin/displaycameras stop +ExecReload=/usr/bin/displaycameras restart + +[Install] +WantedBy=multi-user.target diff --git a/example_layouts/layout.1440x900.3x3 b/example_layouts/layout.1440x900.3x3 new file mode 100644 index 0000000..ca5c6c7 --- /dev/null +++ b/example_layouts/layout.1440x900.3x3 @@ -0,0 +1,95 @@ +# This is the camera feed/windows layout configuration file for the +# displaycameras service. It ONLY configures the layout and feeds for +# the cameras; the rest of the configuration is in displaycameras.conf. +# See the comments in that file for notes on configuring the below. + +# Window names + +windows=(upper_left upper_middle upper_right center_left center_middle center_right lower_left lower_middle lower_right off_screen off_screen2 off_screen3 off_screen4 off_screen5) +# Make sure to account for each window above in the list below. + +# Windows positions + +window_positions=( +#First Row +#upper_left +# 480x300 +"0 0 479 299" \ +#upper_middle +"480 0 959 299" \ +#upper_right +"960 0 1439 299" \ + +#Second Row +#center_left +"0 300 479 599" \ +#center_middle +"480 300 959 599" \ +#center_right +"960 300 1439 599" \ + +#Third Row +#lower_left +"0 600 479 899" \ +#lower_middle +"640 600 959 899" \ +#lower_right +"1280 600 1439 899" \ + + +#off-screen +"1440 0 1919 299" \ +"1920 0 2399 299" \ +"2400 0 2879 299" \ +"1400 300 1919 599" \ +"1920 300 2399 599" \ +"1920 300 2879 599" \ +) + +# Camera Names + +#camera_names=(NE SE South SW West Vestibule SW2 West2 Vest2 NE2 SE2) +#camera_names=(NE SE South SW West Vestibule SW2 West2 Vest2 NE2 SE2 South2 SW3 West3 Vest3 NE3) +camera_names=(NE SE South SW West Vestibule 1stFront 1stBack 2ndHall 2ndRecep 2ndStair 3rdHall 3rdRecep 3rdStair) +# Make sure to account for each camera above in the list of feeds below. + +# Camera Feeds + +camera_feeds=( \ +# Mid-Res +#NE +"rtsp://xxx.xxx.xxx.xxx:7447/yyyyy_2" \ +#SE +"" \ +#South +"" \ +#SW +"" \ +#West +"" \ +#Vestibule +"" \ +#1stBack +"" \ +#1stFront +"" \ +#2ndHall +"" \ +#2ndRecep +"" \ +#2ndStair +"" \ +#3rdHall +"" \ +#3rdRecep +"" \ +#3rdStair +"" \ +#Vest3 +"" \ +#NE3 +"" \ +) + +# Are we rotating cameras through the window matrix? (default false if not set here) +rotate="true" diff --git a/example_layouts/layout.1920x1080.3x3 b/example_layouts/layout.1920x1080.3x3 new file mode 100644 index 0000000..c8da52a --- /dev/null +++ b/example_layouts/layout.1920x1080.3x3 @@ -0,0 +1,98 @@ +# This is the camera feed/windows layout configuration file for the +# displaycameras service. It ONLY configures the layout and feeds for +# the cameras; the rest of the configuration is in displaycameras.conf. +# See the comments in that file for notes on configuring the below. + +# Window names + +# 2x2 screen with 3 off-screen windows +windows=(upper_left upper_middle upper_right center_left center_middle center_right lower_left lower_middle lower_right off_screen off_screen2 off_screen3 off_screen4 off_screen5) +# Make sure to account for each window above in the list below. + +# Windows positions + +window_positions=( +#First Row +#upper_left +# 640x360 +"0 0 639 359" \ +#upper_middle +"640 0 1279 359" \ +#upper_right +"1280 0 1920 359" \ + +#Second Row (missing all but the far right window because large_left is double size +#center_left +# 640x360 +"0 360 639 719" \ +#center_middle +"640 360 1279 719" \ +#center_right +"1280 360 1920 719" \ + +#Third Row +#lower_left +# 640x360 +"0 720 639 1079" \ +#lower_middle +"640 720 1279 1079" \ +#lower_right +"1280 720 1919 1079" \ + + +#off-screen +"1920 0 2559 359" \ +"1920 360 2559 719" \ +"1920 720 2559 1079" \ +"2660 0 3299 359" \ +"2660 360 3299 719" \ +"2660 720 3299 1079" \ +) + +# Camera Names + +#camera_names=(NE SE South SW West Vestibule SW2 West2 Vest2 NE2 SE2) +#camera_names=(NE SE South SW West Vestibule SW2 West2 Vest2 NE2 SE2 South2 SW3 West3 Vest3 NE3) +camera_names=(NE SE South SW West Vestibule 1stFront 1stBack 2ndHall 2ndRecep 2ndStair 3rdHall 3rdRecep 3rdStair) +# Make sure to account for each camera above in the list of feeds below. + +# Camera Feeds + +camera_feeds=( \ +# Mid-Res +#NE +"rtsp://xxx.xxx.xxx.xxx:7447/yyyyy_2" \ +#SE +"" \ +#South +"" \ +#SW +"" \ +#West +"" \ +#Vestibule +"" \ +#1stBack +"" \ +#1stFront +"" \ +#2ndHall +"" \ +#2ndRecep +"" \ +#2ndStair +"" \ +#3rdHall +"" \ +#3rdRecep +"" \ +#3rdStair +"" \ +#Vest3 +"" \ +#NE3 +"" \ +) + +# Are we rotating cameras through the window matrix? (default false if not set here) +rotate="true" diff --git a/example_layouts/layout.conf.1280x1028 b/example_layouts/layout.conf.1280x1028 new file mode 100644 index 0000000..59619a8 --- /dev/null +++ b/example_layouts/layout.conf.1280x1028 @@ -0,0 +1,73 @@ +# This is the camera feed/windows layout configuration file for the +# displaycameras service. It ONLY configures the layout and feeds for +# the cameras; the rest of the configuration is in displaycameras.conf. +# See the comments in that file for notes on configuring the below. + +# This example defines nine 640x343 windows, three of which are off-screen to the right, +# on which the service displays six camera feeds (it uses only the six on-screen windows) +# on a 1280x1028 monitor. If this suites your needs, modify only the camera names to taste +# and feed URLs to what your cameras or NVR provides. + +# Window names + +# 2x3 screen (for 1280x1028 screens) +windows=(upper_left upper_right mid_left mid_right lower_left lower_right off_screen off_screen2 off_screen3) +# Make sure to account for each window above in the list below. + +# Windows positions + +window_positions=( +#First Row +#upper_left +# 640x343 +"0 0 639 342" \ +#upper_right +"640 0 1279 342" \ + +#Second Row +#mid_left +"0 343 639 685" \ +#mid_right +"640 343 1279 685" \ + +#Third Row +#lower_left +"0 686 639 1028" \ +#lower_right +"640 686 1279 1028" \ + +#off-screen +# 640x343 window just off-screen to the right +"1280 0 1919 342" \ +# 640x343 window just below the other +"1280 360 1919 685" \ +"1920 0 2559 342" \ +) + +# Camera Names + +camera_names=(NE SE South SW West Vestibule) +# Make sure to account for each camera above in the list of feeds below. + +# Camera Feeds + +camera_feeds=( +# Low-Res +# "rtsp://xxx.xxx.xxx.xxx/yyyyy_2" \ +#NE +"" \ +#SE +"" \ +#South +"" \ +#SW +"" \ +#West +"" \ +#Vestibule +"" \ +) + +# Are we rotating cameras through the window matrix? Set this explicitly to +# "false" if not desired in this display layout. +rotate="false" diff --git a/example_layouts/layout.conf.1280x720 b/example_layouts/layout.conf.1280x720 new file mode 100644 index 0000000..3abc7e9 --- /dev/null +++ b/example_layouts/layout.conf.1280x720 @@ -0,0 +1,67 @@ +# This is the camera feed/windows layout configuration file for the +# displaycameras service. It ONLY configures the layout and feeds for +# the cameras; the rest of the configuration is in displaycameras.conf. +# See the comments in that file for notes on configuring the below. + +# This example defines seven 640x360 windows, three of which are off-screen to the right, +# through which the service rotates six camera feeds (it actually uses only six windows) +# on a 1280x720 monitor. If this suites your needs, modify only the camera names to taste +# and feed URLs to what your cameras or NVR provides. + +# Window names + +# 2x2 screen (for 1280x720 screens) +windows=(upper_left upper_right lower_left lower_right off_screen off_screen2) +# Make sure to account for each window above in the list below. + +# Windows positions + +window_positions=( +#First Row +#upper_left +# 640x360 +"0 0 639 359" \ +#upper_right +"640 0 1279 359" \ + +#Second Row +#lower_left +"0 360 639 719" \ +#lower_right +"640 360 1279 719" \ + +#off-screen +# 640x360 window just off-screen to the right +"1280 0 1919 359" \ +# 640x360 window just below the other +"1280 360 1919 719" \ +"1920 0 2559 359" \ +) + +# Camera Names + +camera_names=(NE SE South SW West Vestibule) +# Make sure to account for each camera above in the list of feeds below. + +# Camera Feeds + +camera_feeds=( +# Low-Res +# "rtsp://xxx.xxx.xxx.xxx/yyyyy_2" \ +#NE +"" \ +#SE +"" \ +#South +"" \ +#SW +"" \ +#West +"" \ +#Vestibule +"" \ +) + +# Are we rotating cameras through the window matrix? Set this explicitly to +# "false" if not desired in this display layout. +rotate="true" diff --git a/example_layouts/layout.conf.1280x768 b/example_layouts/layout.conf.1280x768 new file mode 100644 index 0000000..8365662 --- /dev/null +++ b/example_layouts/layout.conf.1280x768 @@ -0,0 +1,67 @@ +# This is the camera feed/windows layout configuration file for the +# displaycameras service. It ONLY configures the layout and feeds for +# the cameras; the rest of the configuration is in displaycameras.conf. +# See the comments in that file for notes on configuring the below. + +# This example defines seven 640x384 windows, three of which are off-screen to the right, +# through which the service rotates six camera feeds (it actually uses only six windows) +# on a 1280x768 monitor. If this suites your needs, modify only the camera names to taste +# and feed URLs to what your cameras or NVR provides. + +# Window names + +# 2x2 screen (for 1280x768 screens) +windows=(upper_left upper_right lower_left lower_right off_screen off_screen2) +# Make sure to account for each window above in the list below. + +# Windows positions + +window_positions=( +#First Row +#upper_left +# 640x384 +"0 0 639 383" \ +#upper_right +"640 0 1279 383" \ + +#Second Row +#lower_left +"0 360 639 767" \ +#lower_right +"640 360 1279 767" \ + +#off-screen +# 640x384 window just off-screen to the right +"1280 0 1919 383" \ +# 640x384 window just below the other +"1280 360 1919 767" \ +"1920 0 2559 383" \ +) + +# Camera Names + +camera_names=(NE SE South SW West Vestibule) +# Make sure to account for each camera above in the list of feeds below. + +# Camera Feeds + +camera_feeds=( +# Low-Res +# "rtsp://xxx.xxx.xxx.xxx/yyyyy_2" \ +#NE +"" \ +#SE +"" \ +#South +"" \ +#SW +"" \ +#West +"" \ +#Vestibule +"" \ +) + +# Are we rotating cameras through the window matrix? Set this explicitly to +# "false" if not desired in this display layout. +rotate="true" diff --git a/example_layouts/layout.conf.1440x900 b/example_layouts/layout.conf.1440x900 new file mode 100644 index 0000000..64dbb09 --- /dev/null +++ b/example_layouts/layout.conf.1440x900 @@ -0,0 +1,65 @@ +# This is the camera feed/windows layout configuration file for the +# displaycameras service. It ONLY configures the layout and feeds for +# the cameras; the rest of the configuration is in displaycameras.conf. +# See the comments in that file for notes on configuring the below. + +# This example defines seven 720x450 windows, three of which are off-screen to the right, +# through which the service rotates six camera feeds (it actually uses only six windows) +# on a 1440x900 monitor. If this suites your needs, modify only the camera names to taste +# and feed URLs to what your cameras or NVR provides. + +# Window names + +# 2x2 screen (for 1440x900 screens) +windows=(upper_left upper_right lower_left lower_right off_screen off_screen2 off_screen3) +# Make sure to account for each window above in the list below. + +# Windows positions + +window_positions=( +#First Row +#upper_left +# 720x450 +"0 0 719 449" \ +#upper_right +"720 0 1439 449" \ + +#Second Row +#lower_left +"0 450 719 899" \ +#lower_right +"720 450 1439 899" \ + +#off-screen +"1440 0 2159 449" \ +"1440 450 2159 899" \ +"2160 0 2879 449" \ +) + +# Camera Names + +camera_names=(NE SE South SW West Vestibule) +# Make sure to account for each camera above in the list of feeds below. + +# Camera Feeds + +camera_feeds=( +# Low-Res +# "rtsp://xxx.xxx.xxx.xxx/yyyyy_2" \ +#NE +"" \ +#SE +"" \ +#South +"" \ +#SW +"" \ +#West +"" \ +#Vestibule +"" \ +) + +# Are we rotating cameras through the window matrix? Set this explicitly to +# "false" if not desired in this display layout. +rotate="true" diff --git a/example_layouts/layout.conf.large_left b/example_layouts/layout.conf.large_left new file mode 100644 index 0000000..07c85a6 --- /dev/null +++ b/example_layouts/layout.conf.large_left @@ -0,0 +1,86 @@ +# This is the camera feed/windows layout configuration file for the +# displaycameras service. It ONLY configures the layout and feeds for +# the cameras; the rest of the configuration is in displaycameras.conf. +# See the comments in that file for notes on configuring the below. + +# This is a layout file intended to emulate the layout for six cameras +# in the Unifi system (with one large, mid-res feed in the upper left +# and smaller, low-res feeds arrayed around the right and bottom) on a +# 1080p monitor. + +# You might use this as a layout.conf.defaultlayout file and remove +# the /etc/layout.conf.1920x1080 file if one exists (or enable display +# resolution autodetection and make this file your 1920x1080 layout config file). +# It will never match autodetected display resolution and applied automatically +# with the "large_left" file name suffix. + +# Window names + +# Large Upper Left with two to the right and three below (like the UBNT layout) +windows=(large_left upper_right mid_right lower_left lower_center lower_right off_screen off_screen2 off_screen3) +# Make sure to account for each window above in the list below. + +# Windows positions + +window_positions=( +#First Row +#large_left 1280x720 +"0 0 1279 719" \ +#upper_right +# 640x360 +"1280 0 1919 359" \ + +#Second Row (missing all but the far right window because large_left is double size +#mid_right +"1280 360 1919 719" \ + +#Third Row (all the way across the bottom) +#lower_left +# 640x360 +"0 720 639 1079" \ +#lower_center +# 640x360 +"640 720 1279 1079" \ +#lower_right +# 640x360 +"1280 720 1919 1079" \ + +#off-screen +# 640x360 window just off-screen to the right +"1920 0 2559 359" \ +# 640x360 window just below the other +"1920 360 2559 719" \ +# 640x360 window just below the other two +"1920 720 2559 1079") +) + +# Camera Names + +camera_names=(SE NE South West Vestibule SW) +# Make sure to account for each camera above in the list of feeds below. + +# Camera Feeds + +camera_feeds=( \ +# Mid-Res +# "rtsp://xxx.xxx.xxx.xxx/yyyyy_1" \ +#SE +"" \ +#Low-Res +# "rtsp://xxx.xxx.xxx.xxx/yyyyy_2" \ +#NE +"" \ +#South +"" \ +#West +"" \ +#Vestibule +"" \ +#SW +"" \ +) + +# Are we rotating cameras through the window matrix? (default false if not set here) +# You're REALLY not going to want to rotate these as the RPi will have to do +# significant downscaling on the Hi-Res feed to display it in the smaller windows. +#rotate="true" \ No newline at end of file diff --git a/example_layouts/layout.examples b/example_layouts/layout.examples new file mode 100644 index 0000000..9d8e090 --- /dev/null +++ b/example_layouts/layout.examples @@ -0,0 +1,197 @@ +#### Layout Examples #### + +### Create the Layout ### + +# Figure out the resolution of your target monitor (i.e., HD monitors are 1920x1080). +# If you have the monitor connected to an RPi with Raspbian on it, you can run +# 'fbset -s' to find out the mode of the monitor. +# Take the total number of camera feeds you want to display on that monitor and imagine +# them positioned in a matrix (that may extend off-screen if you have more cameras than +# are conveniently displayed in a 2x2 or 3x3 grid. The size of those grid windows will +# be the monitor's mode dimensions divided by the number of cells in the x and y directions. + +# For instance, you have six camera feeds and a 1080p monitor. That's more displays than +# fits nicely on a 2x2 grid but quite a few less than the nine or more you might put on a +# 3x3 grid. So, you choose to display the six feeds on six 1/2-HD windows (960x540), two +# of which will be off-screen. The feeds will be rotated through the window positions, keeping +# four on-screen and two off, but showing all of them within a few seconds. + +# The window size dictates the maximum resolution of your camera feeds. Avoid asking the RPi +# to downscale video in real time; it won't do well. Upscaling is fine. Small downscaling on +# more powerful RPis (2B, 3B, 3B+) may work fairly well but will increase load. + +### Gather information for the layout configuraton file ### + +# Select RTSP (or whatever) feeds you camera (or NVR) supplies that are equal to or smaller than +# the resolution of your display windows. The examples below generally abide by that guideline. + +# However, in our example /etc/displaycameras/layout.conf.defaultlayout file, we setup for Ubiquiti +# cameras and NVR, RPi 3B or 3B+, six feeds, and 1080p monitors; we have successfully tested a feed +# resolution of 1024x576 on that equipment in our environment with acceptable load values (<1.0) and memory +# utilization. This breaks our guidelines about selecting resolutions <= window size, but also demonstrates +# when that is ok (i.e., we're not asking the hardware to output more resoution than it will support +# [4k] in total camera feeds, the downscaling is relatively minor, and we have sufficient hardware +# and network bandwidth). We also want the crisp display of a slightly downscaled feed over the almost +# 150% upscaled low-res feed (in a 960x540 window), especially since we have the resources. + +# Record your window names and coordinates (on-screen [and off if you plan to rotate a large +# array of cameras through a smaller array of on screen windows]), cameras names +# and camera feeds. + +# Camera names are used to identify the individual omxplayer instances playing each of them. +# The camera feeds should be setup in the same order as the names. +# Window names are not used for very much and are mostly to help make sense of the layout files. +# Window coordinates are crucial, and their order defines where the camera feeds are initially +# displayed on startup (i.e., the first camera name/feed in the first window). If rotation is enabled, +# camera feeds progress through the windows as in the order they are defined here (usually left-to-right, +# top-to-bottom). Rotation is disabled by default; so, if you need to rotate, remember +# to uncomment the rotation="true" line. + +### Record the Layout ### + +# It is important to configure the /etc/displaycameras/layout.conf.defaultlayout file at a very +# minimum. Example layout files for several screen resolutions are included in the /etc/displaycameras +# directory. + +# At a minimum, in the default layout configuration file, setup display window names, coordinates, camera names +# and associated feeds. You may have more windows than cameras, but not vice versa. + +# If there is any chance the RPi will move from display to display, or you want a fleet or RPis to auto-detect +# display resolution and select a pre-defined layout configuration file based on that resolution, you should +# enable 'displaydetect' in the global options above, and setup as many pre-defined layout files as possible +# with the naming convention of /etc/displaycameras/layout.conf. where is the target display's +# resolution (e.g. /etc/displaycameras/layout.conf.1440x900 for a 1440x900 display). Displays whose mode +# does not have a corresponding layout configuration file will use the default layout file. + +## Window names + +# Configure at least as many windows as there are cameras. Use off-screen +# Windows to render cameras off-screen and rotate them back on (showing more +# cameras than there are on-screen windows. Unused off-screen windows are +# ignored as long as they are at the end of the array. + +# !!!! WARNING !!!! +# Never, never, never configure window space with negative x or y positions!!! +# Off screen to the left or above the primary monitor Window coordinates like +# ""-960 0 -1 539" \" are broken. +# omxplayer is documented as supporting them, but it creates broken playback in testing. + +# 2x2 screen with 3 off-screen windows +#windows=(upper_left upper_right lower_left lower_right off_screen off_screen2 off_screen3) +# 3x3 screen with 3 off-screen windows +#windows=(upper_left upper_center upper_right mid_left mid_center mid_right lower_left lower_center lower_right off_screen off_screen2 off_screen3) +# Large Upper Left with two to the right and three below (like the UBNT layout) +#windows=(large_left upper_right mid_right lower_left lower_center lower_right off_screen off_screen2 off_screen3) +# Make sure to account for each window above in the list below. + +## Windows positions + +# Use mid-res feeds with 2x2 layout with 2 rows of 1/2HD windows (960x540). +# I recommend commenting out the second row with a 2x2 layout (and just using +# the 3rd row). Ensure all uncommented lines end with " \". +# Use low-res feeds with 3x3 layout with 3 rows of 1/3HD windows (640x360). + +#window_positions=( +#First Row +#large_left 1280x720 +#"0 0 1279 719" \ +#upper_left +# 960x540 +#"0 0 959 539" \ +# 640x360 +#"0 0 639 359" \ +# 720x450 +#"0 0 719 449" \ +#upper_center +# 640x360 +#"640 0 1279 359" \ +#upper_right +# 960x540 +#"960 0 1920 539" \ +# 640x360 +#"1280 0 1920 359" \ +# 720x450 +#"720 0 1439 449" \ + +#Second Row (missing all but the far right window because large_left is double size +# These windows will only be 640x360 in a 3-row layout (3x3, probably). +#mid_left +#"0 360 639 719" \ +#mid_center +#"640 360 1279 719" \ +#mid_right +#"1280 360 1920 719" \ + +#Third Row (all the way across the bottom) +#lower_left +# 960x540 +#"0 540 959 1079" \ +# 640x360 +#"0 720 639 1079" \ +# 720x450 +#"0 450 719 899" \ +#lower_center +# 640x360 +#"640 720 1279 1079" \ +#lower_right +# 960x540 +#"960 540 1919 1079" \ +# 640x360 +#"1280 720 1919 1079" \ +# 720x450 +#"720 450 1439 899" \ + +#off-screen +# Three each of either 1/3HD or 1/2HD windows (corresponding to 3x3 and 2x2 +# layouts). 3x3 layouts do best with low-res feeds. 2x2 is best with mid-res. +# For the love of God, do not ask the Pi to scale DOWN feeds; don't use mid-res +# feeds in a 3x3 layout. +# 640x360 window just off-screen to the right +#"1920 0 2559 359" \ +# 720x450 +#"1440 0 2159 449" \ +# 960x540 window just off-screen to the right +#"1920 0 2879 539" \ +# 640x360 window just below the other +#"1920 360 2559 719" \ +# 720x450 +#"1440 450 2159 899" \ +# 960x540 window just below the other +#"1920 540 2879 1079" \ +# 640x360 window just below the other two +#"1920 720 2559 1079" \ +# 960x540 window just to the right of the first +#"2880 0 3839 539" \ +#) + +## Camera Names + +#camera_names=(NE SE South SW West Vestibule) +# Make sure to account for each camera above in the list of feeds below. + +## Camera Feeds + +# Account for each camera name by putting its feed in the array below. +# Ensure each line ends in " \". +# Pick appropriate resolution feeds for your window layout. 3x3 layouts should +# use low-res feeds. 2x2 fit mid-res with a bit of upscaling. Large left +# windows also fit a mid-res feed. + +# Hi-Res (don't use unless displaying only one window full screen +#camera_feeds=( \ +#NE +#"" \ +#SE +#"" \ +#South +#"" \ +#SW +#"" \ +#West +#"" \ +#Vestibule +#"" \ +#) + +# Are we rotating? +# rotation="true" diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..4f58cab --- /dev/null +++ b/install.sh @@ -0,0 +1,138 @@ +#!/bin/bash +# Run as root to install the displaycameras package for streaming video feeds. +# Systemd init system is presumed. If installing on 'nix with other init +# systems, you will have to edit this script or enable the displaycameras +# service with available tools for your init system. The main script, +# normally installed at /usr/bin/displaycameras has an LSB header and will run +# as a systemv init script (if copied to /etc/init.d/). No other init systems +# have been tested. + +# What is the path to the installer? +DIR=`dirname "$(readlink -f "$0")"` + +# Ensure prerequisites are installed. + +for package in omxplayer fbi +do +if [ "`dpkg-query -s $package | grep Status | awk -v N=4 '{print $4}'`" != "installed" ]; then + apt-get install $package -y +fi +done + +# Put the files in place and set ownership and permissions. + +if [ -r $DIR/displaycameras ]; then + echo "Copying the main script and setting permissions." + cp -f $DIR/displaycameras /usr/bin/ && chown root:root /usr/bin/displaycameras && chmod 0755 /usr/bin/displaycameras +else + echo "The displaycameras file is missing or unreadable. This is a critical file." + echo "Verify package contents." + exit 1 +fi +if [ -r $DIR/displaycameras.service ]; then + echo "Copying the systemd init file and setting permissions." + cp -f $DIR/displaycameras.service /etc/systemd/system/ && chown root:root /etc/systemd/system/displaycameras.service && chmod 0755 /etc/systemd/system/displaycameras.service +else + echo "The displaycameras.service file is missing or unreadable. This is a critical file." + echo "Verify package contents." + exit 2 +fi +# Config files, cron job, gpu memory split, and disable overscan support only if not upgrading +if [ "$1" != "upgrade" ]; then + if [ -r $DIR/displaycameras.conf ]; then + if [ -r /etc/displaycameras/displaycameras.conf ]; then + [ -d /etc/displaycameras/bak ] || mkdir /etc/displaycameras/bak + for i in `find /etc/displaycameras/ -maxdepth 1 -type f`; do + mv -f $i /etc/displaycameras/bak/ + done + echo "Your config files were backed up to /etc/displaycameras/bak" + fi + echo "Copying the global and layout configuration files." + [ -d /etc/displaycameras ] || mkdir /etc/displaycameras + cp -f $DIR/layout.conf.default /etc/displaycameras/ && chown root:root /etc/displaycameras/layout.conf.default && chmod 0644 /etc/displaycameras/layout.conf.default + cp -f $DIR/displaycameras.conf /etc/displaycameras/ && chown root:root /etc/displaycameras/displaycameras.conf && chmod 0644 /etc/displaycameras/displaycameras.conf + else + echo "The displaycameras.conf file is missing or unreadable. This is a critical file." + echo "Verify package contents." + exit 3 + fi + if [ -r $DIR/repaircameras.cron ]; then + echo "Copying the repaircameras cron job and reloading cron." + cp -f $DIR/repaircameras.cron /etc/cron.d/repaircameras && chown root:root /etc/cron.d/repaircameras && chmod 0755 /etc/cron.d/repaircameras + systemctl restart cron + else + echo "The repaircameras.cron file is missing or unreadable. This is a critical file." + echo "Verify package contents." + exit 4 + fi + # Set a reasonable GPU memory allocation + # Determine total physical memory + # System Memory + sysmem="`free -m | grep Mem: | awk '$1=$1' | cut -f 2 -d " "`" + # GPU Memory + gpumem="`sudo raspi-config nonint get_config_var gpu_mem /boot/config.txt`" + # Total Mem + physmem=$((gpumem + sysmem)) + if [ "$physmem" -lt "500" ]; then + split=96 + else + if [ "$physmem" -lt "1000" ]; then + split=192 + else + split=256 + fi + fi + # Ask whether there's a custom split desired + echo -n "Enter a custom gpu split if desired [gpu memory in MB] or [Enter] to use recommended split" + read + if [ "$REPLY" != "" ]; then + if [ "$REPLY" -ge "64" -a "$REPLY" -le "512" ]; then + split="$REPLY" + fi + fi + # Set the split + if [ "`raspi-config nonint get_config_var gpu_mem /boot/config.txt`" -lt "$split" ]; then + echo "Setting gpu_mem allocation to "$split"MB" + raspi-config nonint do_memory_split "$split" + fi + # Disable overscan support so that display resolution autodetection works + if [ "`raspi-config nonint get_overscan`" = "0" ]; then + echo "Disabling display overscan compensation. Set your monitor not to overscan." + raspi-config nonint do_overscan 1 + fi +fi +if [ -r $DIR/omxplayer_dbuscontrol ]; then + echo "Copying the omxplayer control script." + cp -f $DIR/omxplayer_dbuscontrol /usr/bin/ && chown root:root /usr/bin/omxplayer_dbuscontrol && chmod 0755 /usr/bin/omxplayer_dbuscontrol +else + echo "The omxplayer_dbuscontrl file is missing or unreadable. This is a critical file." + echo "Verify package contents." + exit 5 +fi +if [ -r $DIR/rotatedisplays ]; then + echo "Copying the display rotating script and setting permissions." + cp -f $DIR/rotatedisplays /usr/bin/ && chown root:root /usr/bin/rotatedisplays && chmod 0755 /usr/bin/rotatedisplays +else + echo "The rotatedisplays file is missing or unreadable. This file is required to support display rotation." + echo "Verify package contents." +fi +if [ -r $DIR/black.png ]; then + echo "Copying the black background file and setting ownership." + cp -f $DIR/black.png /usr/bin/ && chown root:root /usr/bin/black.png +else + echo "The black.png file is missing or unreadable. Screen blanking will not work" + echo "with out it. Verify package contents." +fi + +# Update systemd and enable the displaycameras service. +systemctl daemon-reload +systemctl enable displaycameras + +echo "Installation Successful!" +read -p "See the README? [Y/y/N/n]" +if [ "$REPLY" = "Y" -o "$REPLY" = "y" ]; then + echo "Use the space bar (or PgDn) to page down, PgUp to page up, q to quit" + read -p "Press Enter to begin." + less $DIR/README +fi +exit 0 \ No newline at end of file diff --git a/layout.conf.default b/layout.conf.default new file mode 100644 index 0000000..1262feb --- /dev/null +++ b/layout.conf.default @@ -0,0 +1,72 @@ +# This is the camera feed/windows layout configuration file for the +# displaycameras service. It ONLY configures the layout and feeds for +# the cameras; the rest of the configuration is in displaycameras.conf. +# See the comments in that file for notes on configuring the below. + +# This example defines seven 1/2-HD windows, three of which are off-screen to the right, +# through which the service rotates six camera feeds (it actually uses only six windows) +# on a full-HD monitor. If this suites your needs, modify only the camera names to taste +# and feed URLs to what your cameras or NVR provides. + +# Window names + +# 2x2 screen with 3 off-screen windows +windows=(upper_left upper_right lower_left lower_right off_screen off_screen2 off_screen3) +# Make sure to account for each window above in the list below. + +# Windows positions + +window_positions=( +#First Row +#upper_left +# 960x540 +"0 0 959 539" \ +#upper_right +# 960x540 +"960 0 1920 539" \ + +#Second Row (missing all but the far right window because large_left is double size +#lower_left +# 960x540 +"0 540 959 1079" \ +#lower_right +# 960x540 +"960 540 1919 1079" \ + +#off-screen +# 960x540 window just off-screen to the right +"1920 0 2879 539" \ +# 960x540 window just below the other +"1920 540 2879 1079" \ +# 960x540 window just off-screen to the left +"2880 0 3839 539" \ +) + +# Camera Names + +camera_names=(NE SE South SW West Vestibule) +# Make sure to account for each camera above in the list of feeds below. + +# Camera Feeds + +camera_feeds=( \ +# Mid-Res if your RPi can handle the load +# "rtsp://xxx.xxx.xxx.xxx/yyyyy_1" \ +# Low-Res otherwise +# "rtsp://xxx.xxx.xxx.xxx/yyyyy_2" \ +#NE +"" \ +#SE +"" \ +#South +"" \ +#SW +"" \ +#West +"" \ +#Vestibule +"" \ +) + +# Are we rotating cameras through the window matrix? (default false if not set here) +# rotate="true" \ No newline at end of file diff --git a/omxplayer_dbuscontrol b/omxplayer_dbuscontrol new file mode 100644 index 0000000..ee4f80b --- /dev/null +++ b/omxplayer_dbuscontrol @@ -0,0 +1,86 @@ +#!/bin/bash + +# Based on dbus.sh from the https://github.com/anselanza/omx-layers project +#set -x + +# This script is specifically modified to support multiple omxplayer instances +# registered at custom dbus addresses (for use with RPis and Ubiquity camera +# systems. Since these instances run as background processes as root and the +# RPi is presumed to be single use (with no other omxplayer instances running, +# it is protected from being run by regular user. +# If non-root operation is desired, comment out the next four lines. +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root" + exit 1 +fi + +OMXPLAYER_DBUS_ADDR="/tmp/omxplayerdbus.${USER:-root}" +OMXPLAYER_DBUS_PID="/tmp/omxplayerdbus.${USER:-root}.pid" +export DBUS_SESSION_BUS_ADDRESS=`cat $OMXPLAYER_DBUS_ADDR` +export DBUS_SESSION_BUS_PID=`cat $OMXPLAYER_DBUS_PID` + +[ -z "$DBUS_SESSION_BUS_ADDRESS" ] && { echo "Must have DBUS_SESSION_BUS_ADDRESS" >&2; exit 1; } + +case $2 in +getplaystatus) + playstatus=`dbus-send --print-reply=literal --session --reply-timeout=500 --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.PlaybackStatus 2>/dev/null` + [ $? -ne 0 ] && exit 1 + playstatus="$(sed 's/^ *//;s/ *$//;' <<< "$playstatus")" + echo $playstatus + ;; +status) + playstatus=`dbus-send --print-reply=literal --session --reply-timeout=500 --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.PlaybackStatus 2>/dev/null` + [ $? -ne 0 ] && exit 1 + playstatus="$(sed 's/^ *//;s/ *$//;' <<< "$playstatus")" + source=$(dbus-send --print-reply=literal --session --reply-timeout=500 --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.GetSource 2>/dev/null) + [ $? -ne 0 ] && exit 1 + source="$(sed 's/^ *//;s/ *$//;' <<< "$source")" + position=`dbus-send --print-reply=literal --session --reply-timeout=500 --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Position 2>/dev/null` + [ $? -ne 0 ] && exit 1 + position="$(awk '{print $2}' <<< "$position")" + position="$(($position/1000000))sec" + echo "$playstatus $source" + echo "at $position" +;; +getduration) + duration=`dbus-send --print-reply=literal --session --reply-timeout=500 --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Duration 2>/dev/null` + [ $? -ne 0 ] && exit 1 + duration="$(awk '{print $2}' <<< "$duration")" + duration="$(($duration/1000000)) sec" + echo $duration + ;; +getposition) + position=`dbus-send --print-reply=literal --session --reply-timeout=500 --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Position 2>/dev/null` + [ $? -ne 0 ] && exit 1 + position="$(awk '{print $2}' <<< "$position")" + position="$(($position/1000000))s" + echo $position + ;; +setvideopos) + dbus-send --print-reply=literal --session --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.VideoPos objpath:/not/used string:"$3" >/dev/null + ;; +setalpha) + dbus-send --print-reply=literal --session --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.SetAlpha objpath:/not/used int64:"$3" >/dev/null + ;; +setvideocroppos) + dbus-send --print-reply=literal --session --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.SetVideoCropPos objpath:/not/used string:"$3 $4 $5 $6" >/dev/null + ;; +getsource) + source=$(dbus-send --print-reply=literal --session --reply-timeout=500 --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.GetSource 2>/dev/null) + [ $? -ne 0 ] && exit 1 + echo "$source" | sed 's/^ *//' + ;; +stop) + dbus-send --print-reply=literal --session --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Stop >/dev/null + ;; +pause) + dbus-send --print-reply=literal --session --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Pause >/dev/null + ;; +quit) + dbus-send --print-reply=literal --session --dest=org.mpris.MediaPlayer2.omxplayer.$1 /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Quit 2>/dev/null + ;; +*) + echo "usage: $0 screen_name stop|pause|quit|status|getplaystatus|getsource|getduration|getposition" >&2 + exit 1 + ;; +esac diff --git a/repaircameras.cron b/repaircameras.cron new file mode 100644 index 0000000..5db4295 --- /dev/null +++ b/repaircameras.cron @@ -0,0 +1,6 @@ +# This job repairs broken camera feeds in the displaycamera service + +SHELL=/bin/bash +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +* * * * * root /usr/bin/displaycameras repair diff --git a/rotatedisplays b/rotatedisplays new file mode 100644 index 0000000..8ea2499 --- /dev/null +++ b/rotatedisplays @@ -0,0 +1,7 @@ +#!/bin/bash +for i in `seq 1 11`; do +sleep $1 +/usr/bin/displaycameras rotate >/dev/null 2>&1 +done +$0 $1 & +exit 0