Kaynağa Gözat

roll rtsp into release

Alfonso Gamboa 4 yıl önce
ebeveyn
işleme
b8eb5ae8a0

+ 12 - 0
README.md

@@ -122,10 +122,22 @@ socat TCP4-LISTEN:9000,reuseaddr,fork /dev/ttyUSB0,raw,echo=0
 
 Change ```/dev/ttyUSB0``` to whatever path your spotlight enumerated to if necessary.  The camera will now be able to control the spotlight.
 
+---
+To enable RTSP streaming, change the following lines, you can choose to enable or disable audio.
+
+```
+RTSP_ENABLED="false"
+RTSP_ENABLE_AUDIO="false"
+```
+the stream will be located at ```rtsp://IP_ADDRESS:8554/unicast```
+
+Note:  VLC seems to work fine for playback, ffmpeg and others have severe artifacts in the stream during playback.
+
 ---
 
 ## Latest Updates
 
+* 04-19-22:  Add RTSP Server functionality
 * 04-17-22:  Add remote spotlight accessory capability
 * 04-15-22:  Enable USB Direct functionality. Allows you to connect camera using a USB cable to a device supporting CDC_NCM devices to get an internet connection, no USB Ethernet Adapter required.  
 * 04-14-22:  Fix kernel command line memory mappings, resolves stability issues

BIN
SD_ROOT/wz_mini/bin/v4l2rtspserver


+ 634 - 0
SD_ROOT/wz_mini/etc/alsa.conf

@@ -0,0 +1,634 @@
+#
+#  ALSA library configuration file
+#
+
+# pre-load the configuration files
+
+@hooks [
+	{
+		func load
+		files [
+			{
+				@func concat
+				strings [
+					{ @func datadir }
+					"/alsa.conf.d/"
+				]
+			}
+			"/etc/asound.conf"
+			"~/.asoundrc"
+		]
+		errors false
+	}
+]
+
+# load card-specific configuration files (on request)
+
+cards.@hooks [
+	{
+		func load
+		files [
+			{
+				@func concat
+				strings [
+					{ @func datadir }
+					"/cards/aliases.conf"
+				]
+			}
+		]
+	}
+	{
+		func load_for_all_cards
+		files [
+			{
+				@func concat
+				strings [
+					{ @func datadir }
+					"/cards/"
+					{ @func private_string }
+					".conf"
+				]
+			}
+		]
+		errors false
+	}
+]
+
+#
+# defaults
+#
+
+# show all name hints also for definitions without hint {} section
+defaults.namehint.showall off
+# show just basic name hints
+defaults.namehint.basic on
+# show extended name hints
+defaults.namehint.extended off
+#
+defaults.ctl.card 0
+defaults.pcm.card 0
+defaults.pcm.device 0
+defaults.pcm.subdevice -1
+defaults.pcm.nonblock 1
+defaults.pcm.compat 0
+defaults.pcm.minperiodtime 5000		# in us
+defaults.pcm.ipc_key 5678293
+defaults.pcm.ipc_gid audio
+defaults.pcm.ipc_perm 0660
+defaults.pcm.dmix.max_periods 0
+defaults.pcm.dmix.rate 48000
+defaults.pcm.dmix.format "unchanged"
+defaults.pcm.dmix.card defaults.pcm.card
+defaults.pcm.dmix.device defaults.pcm.device
+defaults.pcm.dsnoop.card defaults.pcm.card
+defaults.pcm.dsnoop.device defaults.pcm.device
+defaults.pcm.front.card defaults.pcm.card
+defaults.pcm.front.device defaults.pcm.device
+defaults.pcm.rear.card defaults.pcm.card
+defaults.pcm.rear.device defaults.pcm.device
+defaults.pcm.center_lfe.card defaults.pcm.card
+defaults.pcm.center_lfe.device defaults.pcm.device
+defaults.pcm.side.card defaults.pcm.card
+defaults.pcm.side.device defaults.pcm.device
+defaults.pcm.surround21.card defaults.pcm.card
+defaults.pcm.surround21.device defaults.pcm.device
+defaults.pcm.surround40.card defaults.pcm.card
+defaults.pcm.surround40.device defaults.pcm.device
+defaults.pcm.surround41.card defaults.pcm.card
+defaults.pcm.surround41.device defaults.pcm.device
+defaults.pcm.surround50.card defaults.pcm.card
+defaults.pcm.surround50.device defaults.pcm.device
+defaults.pcm.surround51.card defaults.pcm.card
+defaults.pcm.surround51.device defaults.pcm.device
+defaults.pcm.surround71.card defaults.pcm.card
+defaults.pcm.surround71.device defaults.pcm.device
+defaults.pcm.iec958.card defaults.pcm.card
+defaults.pcm.iec958.device defaults.pcm.device
+defaults.pcm.modem.card defaults.pcm.card
+defaults.pcm.modem.device defaults.pcm.device
+# truncate files via file or tee PCM
+defaults.pcm.file_format	"raw"
+defaults.pcm.file_truncate	true
+defaults.rawmidi.card 0
+defaults.rawmidi.device 0
+defaults.rawmidi.subdevice -1
+defaults.hwdep.card 0
+defaults.hwdep.device 0
+defaults.timer.class 2
+defaults.timer.sclass 0
+defaults.timer.card 0
+defaults.timer.device 0
+defaults.timer.subdevice 0
+
+#
+#  PCM interface
+#
+
+# redirect to load-on-demand extended pcm definitions
+pcm.cards cards.pcm
+
+pcm.default cards.pcm.default
+pcm.sysdefault cards.pcm.default
+pcm.front cards.pcm.front
+pcm.rear cards.pcm.rear
+pcm.center_lfe cards.pcm.center_lfe
+pcm.side cards.pcm.side
+pcm.surround21 cards.pcm.surround21
+pcm.surround40 cards.pcm.surround40
+pcm.surround41 cards.pcm.surround41
+pcm.surround50 cards.pcm.surround50
+pcm.surround51 cards.pcm.surround51
+pcm.surround71 cards.pcm.surround71
+pcm.iec958 cards.pcm.iec958
+pcm.spdif iec958
+pcm.hdmi cards.pcm.hdmi
+pcm.dmix cards.pcm.dmix
+pcm.dsnoop cards.pcm.dsnoop
+pcm.modem cards.pcm.modem
+pcm.phoneline cards.pcm.phoneline
+
+pcm.hw {
+	@args [ CARD DEV SUBDEV ]
+	@args.CARD {
+		type string
+		default {
+			@func getenv
+			vars [
+				ALSA_PCM_CARD
+				ALSA_CARD
+			]
+			default {
+				@func refer
+				name defaults.pcm.card
+			}
+		}
+	}
+	@args.DEV {
+		type integer
+		default {
+			@func igetenv
+			vars [
+				ALSA_PCM_DEVICE
+			]
+			default {
+				@func refer
+				name defaults.pcm.device
+			}
+		}
+	}
+	@args.SUBDEV {
+		type integer
+		default {
+			@func refer
+			name defaults.pcm.subdevice
+		}
+	}		
+	type hw
+	card $CARD
+	device $DEV
+	subdevice $SUBDEV
+	hint {
+		show {
+			@func refer
+			name defaults.namehint.extended
+		}
+		description "Direct hardware device without any conversions"
+	}
+}
+
+pcm.plughw {
+	@args [ CARD DEV SUBDEV ]
+	@args.CARD {
+		type string
+		default {
+			@func getenv
+			vars [
+				ALSA_PCM_CARD
+				ALSA_CARD
+			]
+			default {
+				@func refer
+				name defaults.pcm.card
+			}
+		}
+	}
+	@args.DEV {
+		type integer
+		default {
+			@func igetenv
+			vars [
+				ALSA_PCM_DEVICE
+			]
+			default {
+				@func refer
+				name defaults.pcm.device
+			}
+		}
+	}
+	@args.SUBDEV {
+		type integer
+		default {
+			@func refer
+			name defaults.pcm.subdevice
+		}
+	}		
+	type plug
+	slave.pcm {
+		type hw
+		card $CARD
+		device $DEV
+		subdevice $SUBDEV
+	}
+	hint {
+		show {
+			@func refer
+			name defaults.namehint.extended
+		}
+		description "Hardware device with all software conversions"
+	}
+}
+
+pcm.plug {
+	@args [ SLAVE ]
+	@args.SLAVE {
+		type string
+	}
+	type plug
+	slave.pcm $SLAVE
+}
+
+pcm.shm {
+	@args [ SOCKET PCM ]
+	@args.SOCKET {
+		type string
+	}
+	@args.PCM {
+		type string
+	}
+	type shm
+	server $SOCKET
+	pcm $PCM
+}
+
+pcm.tee {
+	@args [ SLAVE FILE FORMAT ]
+	@args.SLAVE {
+		type string
+	}
+	@args.FILE {
+		type string
+	}
+	@args.FORMAT {
+		type string
+		default {
+			@func refer
+			name defaults.pcm.file_format
+		}
+	}
+	type file
+	slave.pcm $SLAVE
+	file $FILE
+	format $FORMAT
+	truncate {
+		@func refer
+		name defaults.pcm.file_truncate
+	}
+}
+
+pcm.file {
+	@args [ FILE FORMAT ]
+	@args.FILE {
+		type string
+	}
+	@args.FORMAT {
+		type string
+		default {
+			@func refer
+			name defaults.pcm.file_format
+		}
+	}
+	type file
+	slave.pcm null
+	file $FILE
+	format $FORMAT
+	truncate {
+		@func refer
+		name defaults.pcm.file_truncate
+	}
+}
+
+pcm.null {
+	type null
+	hint {
+		show {
+			@func refer
+			name defaults.namehint.basic
+		}
+		description "Discard all samples (playback) or generate zero samples (capture)"
+	}
+}
+
+#
+#  Control interface
+#
+	
+ctl.sysdefault {
+	type hw
+	card {
+		@func getenv
+		vars [
+			ALSA_CTL_CARD
+			ALSA_CARD
+		]
+		default {
+			@func refer
+			name defaults.ctl.card
+		}
+	}
+	hint.description "Default control device"
+}
+ctl.default ctl.sysdefault
+
+ctl.hw {
+	@args [ CARD ]
+	@args.CARD {
+		type string
+		default {
+			@func getenv
+			vars [
+				ALSA_CTL_CARD
+				ALSA_CARD
+			]
+			default {
+				@func refer
+				name defaults.ctl.card
+			}
+		}
+	}
+	type hw
+	card $CARD
+	hint.description "Direct control device"
+}
+
+ctl.shm {
+	@args [ SOCKET CTL ]
+	@args.SOCKET {
+		type string
+	}
+	@args.CTL {
+		type string
+	}
+	type shm
+	server $SOCKET
+	ctl $CTL
+}
+
+#
+#  RawMidi interface
+#
+
+rawmidi.default {
+	type hw
+	card {
+		@func getenv
+		vars [
+			ALSA_RAWMIDI_CARD
+			ALSA_CARD
+		]
+		default {
+			@func refer
+			name defaults.rawmidi.card
+		}
+	}
+	device {
+		@func igetenv
+		vars [
+			ALSA_RAWMIDI_DEVICE
+		]
+		default {
+			@func refer
+			name defaults.rawmidi.device
+		}
+	}
+	hint.description "Default raw MIDI device"
+}
+
+rawmidi.hw {
+	@args [ CARD DEV SUBDEV ]
+	@args.CARD {
+		type string
+		default {
+			@func getenv
+			vars [
+				ALSA_RAWMIDI_CARD
+				ALSA_CARD
+			]
+			default {
+				@func refer
+				name defaults.rawmidi.card
+			}
+		}
+	}
+	@args.DEV {
+		type integer
+		default {
+			@func igetenv
+			vars [
+				ALSA_RAWMIDI_DEVICE
+			]
+			default {
+				@func refer
+				name defaults.rawmidi.device
+			}
+		}
+	}
+	@args.SUBDEV {
+		type integer
+		default -1
+	}
+	type hw
+	card $CARD
+	device $DEV
+	subdevice $SUBDEV
+	hint {
+		description "Direct rawmidi driver device"
+		device $DEV
+	}
+}
+
+rawmidi.virtual {
+	@args [ MERGE ]
+	@args.MERGE {
+		type string
+		default 1
+	}
+	type virtual
+	merge $MERGE
+}
+
+#
+#  Sequencer interface
+#
+
+seq.default {
+	type hw
+	hint.description "Default sequencer device"
+}
+
+seq.hw {
+	type hw
+}
+
+#
+#  HwDep interface
+#
+
+hwdep.default {
+	type hw
+	card {
+		@func getenv
+		vars [
+			ALSA_HWDEP_CARD
+			ALSA_CARD
+		]
+		default {
+			@func refer
+			name defaults.hwdep.card
+		}
+	}
+	device {
+		@func igetenv
+		vars [
+			ALSA_HWDEP_DEVICE
+		]
+		default {
+			@func refer
+			name defaults.hwdep.device
+		}
+	}
+	hint.description "Default hardware dependent device"
+}
+
+hwdep.hw {
+	@args [ CARD DEV ]
+	@args.CARD {
+		type string
+		default {
+			@func getenv
+			vars [
+				ALSA_HWDEP_CARD
+				ALSA_CARD
+			]
+			default {
+				@func refer
+				name defaults.hwdep.card
+			}
+		}
+	}
+	@args.DEV {
+		type integer
+		default {
+			@func igetenv
+			vars [
+				ALSA_HWDEP_DEVICE
+			]
+			default {
+				@func refer
+				name defaults.hwdep.device
+			}
+		}
+	}
+	type hw
+	card $CARD
+	device $DEV
+	hint {
+		description "Direct hardware dependent device"
+		device $DEV
+	}
+}
+
+#
+#  Timer interface
+#
+
+timer_query.default {
+	type hw
+}
+
+timer_query.hw {
+	type hw
+}
+
+timer.default {
+	type hw
+	class {
+		@func refer
+		name defaults.timer.class
+	}
+	sclass {
+		@func refer
+		name defaults.timer.sclass
+	}
+	card {
+		@func refer
+		name defaults.timer.card
+	}
+	device {
+		@func refer
+		name defaults.timer.device
+	}
+	subdevice {
+		@func refer
+		name defaults.timer.subdevice
+	}
+	hint.description "Default timer device"
+}
+
+timer.hw {
+	@args [ CLASS SCLASS CARD DEV SUBDEV ]
+	@args.CLASS {
+		type integer
+		default {
+			@func refer
+			name defaults.timer.class
+		}
+	}
+	@args.SCLASS {
+		type integer
+		default {
+			@func refer
+			name defaults.timer.sclass
+		}
+	}
+	@args.CARD {
+		type string
+		default {
+			@func refer
+			name defaults.timer.card
+		}
+	}
+	@args.DEV {
+		type integer
+		default {
+			@func refer
+			name defaults.timer.device
+		}
+	}
+	@args.SUBDEV {
+		type integer
+		default {
+			@func refer
+			name defaults.timer.subdevice
+		}
+	}
+	type hw
+	class $CLASS
+	sclass $SCLASS
+	card $CARD
+	device $DEV
+	subdevice $SUBDEV
+	hint {
+		description "Direct timer device"
+		device $DEV
+	}
+}

+ 45 - 2
SD_ROOT/wz_mini/etc/init.d/v3_init.sh

@@ -16,11 +16,39 @@ echo '
 
 set -x
 
+echo "mounting tempfs for workspace"
 mount -t tmpfs /tmp
-cp /opt/wz_mini/etc/shadow /tmp/.shadow
-mount --bind /tmp/.shadow /etc/shadow
+mount -t tmpfs /run
+
+echo "create workspace directory"
+mkdir /run/.storage
+
+if [[ $(cat /opt/wz_mini/run_mmc.sh | grep "RTSP_ENABLED\=") == "RTSP_ENABLED\=\"true\"" ]]; then
+cp /etc/init.d/rcS /run/.storage/rcS
+sed -i '/^".*/aset -x' /run/.storage/rcS
+sed -i '/^# Mount configs.*/i cp /system/bin/iCamera /run/.storage/\nmount -o ro,bind /opt/wz_mini/usr/bin/iCamera /system/bin/iCamera\n tail -f /system/bin/iCamera > /dev/null 2>&1 &' /run/.storage/rcS
+sed -i '/sbin:/s/$/:\/opt\/wz_mini\/bin/' /run/.storage/rcS
+sed -i '/system\/\lib/s/$/:\/opt\/wz_mini\/lib/' /run/.storage/rcS
+mount --bind /run/.storage/rcS /etc/init.d/rcS
+echo "load video loopback driver at video1"
+insmod /opt/wz_mini/lib/modules/v4l2loopback.ko video_nr=1
+fi
+
+if [[ $(cat /opt/wz_mini/run_mmc.sh | grep "DEBUG_ENABLED\=") == "DEBUG_ENABLED\=\"true\"" ]]; then
+cp /etc/init.d/rcS /run/.storage/rcS
+sed -i '/app_init.sh/,+2d' /run/.storage/rcS
+sed -i '/^# Run init/i/bin/sh /etc/profile' /run/.storage/rcS
+mount --bind /run/.storage/rcS /etc/init.d/rcS
+fi
+
+echo "replace stock password"
+cp /opt/wz_mini/etc/shadow /run/.storage/shadow
+mount --bind /run/.storage/shadow /etc/shadow
 chmod 400 /etc/shadow
 
+echo "bind /etc/profile for local/ssh shells"
+mount --bind /opt/wz_mini/etc/profile /etc/profile
+
 if [[ -f /opt/wz_mini/swap.gz ]]; then
 	echo "swap archive present, extracting"
         gzip -d /opt/wz_mini/swap.gz
@@ -30,6 +58,21 @@ else
 	echo "swap archive not present, not extracting"
 fi
 
+echo "mount configs partition for dropbear"
+mount -t jffs2 /dev/mtdblock6 /configs
+
+if [[ -d /configs/.ssh ]]; then
+        echo "dropbear ssh config dir present"
+	umount /configs
+else
+        echo "dropbear ssh config dir not present, creating"
+        mkdir /configs/.ssh
+	umount /configs
+fi
+
+echo "Run dropbear ssh server"
+/opt/wz_mini/bin/dropbearmulti dropbear -R -m
+
 { sleep 30; /media/mmc/wz_mini/run_mmc.sh 2> /media/mmc/wz_mini/log/wz_mini_hacks.log; } &
 
 /linuxrc

+ 2 - 2
SD_ROOT/wz_mini/etc/profile

@@ -8,9 +8,9 @@ if [ "$PS1" ]; then
 fi
 
 # Set terminal env
-export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/media/mmc/wz_mini/bin
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/wz_mini/bin
 export PATH=/system/bin:$PATH
-export LD_LIBRARY_PATH=/system/lib:/media/mmc/wz_mini/lib
+export LD_LIBRARY_PATH=/system/lib:/opt/wz_mini/lib
 export LD_LIBRARY_PATH=/thirdlib:$LD_LIBRARY_PATH
 #export TZ=UTC-8
 

BIN
SD_ROOT/wz_mini/lib/libasound.so.2


BIN
SD_ROOT/wz_mini/lib/libcallback.so


BIN
SD_ROOT/wz_mini/lib/libtinyalsa.so.2.0.0


BIN
SD_ROOT/wz_mini/lib/modules/v4l2loopback.ko


+ 43 - 16
SD_ROOT/wz_mini/run_mmc.sh

@@ -15,8 +15,26 @@ USB_DIRECT_MAC_ADDR="02:01:02:03:04:08"
 REMOTE_SPOTLIGHT="false"
 REMOTE_SPOTLIGHT_HOST="0.0.0.0"
 
+RTSP_ENABLED="false"
+RTSP_ENABLE_AUDIO="false"
+
+DEBUG_ENABLED="false"
+
+#####################################
+##########CONFIG END#################
+#####################################
+
 echo  "run_mmc.sh start" > /dev/kmsg
 
+swap_enable() {
+        if [[ -f /media/mmc/wz_mini/swap ]]; then
+                echo "swap exists, enable"
+                swapon /media/mmc/wz_mini/swap
+        else
+                echo "swap missing, system stability with usb potentially comprimised"
+        fi
+}
+
 if [[ -d /configs/.ssh ]]; then
 	echo "dropbear ssh config dir present"
 else
@@ -26,12 +44,7 @@ fi
 
 if [[ "$ENABLE_USB_ETH" == "true" ]]; then
 
-        if [[ -f /media/mmc/wz_mini/swap ]]; then
-                echo "swap exists, enable"
-                swapon /media/mmc/wz_mini/swap
-        else
-		echo "swap missing, system stability with usb potentially comprimised"
-	fi
+	swap_enable
 
         ifconfig eth0 down
         ifconfig wlan0 down
@@ -49,9 +62,7 @@ if [[ "$ENABLE_USB_ETH" == "true" ]]; then
 	        echo "usb ethernet disabled"
 fi
 
-
 if [[ "$ENABLE_USB_DIRECT" == "true" ]]; then
-#	if [[ ! -d /sys/class/net/usb0* ]]; then
 	##ONLY WORKS WITH g_ethernet enabled kernel
         ifconfig usb0 down
         ifconfig wlan0 down
@@ -72,8 +83,8 @@ fi
 if [[ "$DISABLE_FW_UPGRADE" == "true" ]]; then
 	mkdir /tmp/Upgrade
 	mount -t tmpfs -o size=1,nr_inodes=1 none /tmp/Upgrade
-	echo -e "127.0.0.1 localhost \n127.0.0.1 wyze-upgrade-service.wyzecam.com" > /tmp/.hosts_wz
-	mount --bind /tmp/.hosts_wz /etc/hosts
+	echo -e "127.0.0.1 localhost \n127.0.0.1 wyze-upgrade-service.wyzecam.com" > /run/.storage/hosts_wz
+	mount --bind /run/.storage/hosts_wz /etc/hosts
 fi
 
 if [[ "$REMOTE_SPOTLIGHT" == "true" ]]; then
@@ -81,18 +92,34 @@ if [[ "$REMOTE_SPOTLIGHT" == "true" ]]; then
 
 fi
 
+if [[ "$RTSP_ENABLED" == "true" ]]; then
+	swap_enable
+        mkdir /tmp/alsa
+        cp /media/mmc/wz_mini/etc/alsa.conf /tmp/alsa
+
+        if [[ "$RTSP_ENABLE_AUDIO" == "true" ]]; then
+                LD_LIBRARY_PATH=/media/mmc/wz_mini/lib /media/mmc/wz_mini/bin/v4l2rtspserver -C 1 -a S16_LE  /dev/video1,hw:Loopback,0 &
+        else
+                echo "rtsp audio disabled"
+                LD_LIBRARY_PATH=/media/mmc/wz_mini/lib /media/mmc/wz_mini/bin/v4l2rtspserver -s /dev/video1 &
+        fi
+        else
+        echo "rtsp disabled"
+fi
+
 echo "set hostname"
 hostname $HOSTNAME
 
-echo "bind /etc/profile for local shell"
-mount --bind /media/mmc/wz_mini/etc/profile /etc/profile
-
-echo "Run dropbear ssh server"
-/media/mmc/wz_mini/bin/dropbearmulti dropbear -R -m
+echo "clean up tail"
+pkill tail
 
 sleep 3
 
+#################################################
+##############CUSTOM BEGIN#######################
+#################################################
+
 #Place commands here to run 30 seconds after boot
 #such as mount nfs, ping, etc
 
-#mount -t nfs -o nolock,rw,noatime,nodiratime 192.168.1.1:/volume1 /media/mmc/record
+#mount -t nfs -o nolock,rw,noatime,nodiratime 192.168.1.1:/volume1 /media/mmc/record &

+ 5 - 0
SD_ROOT/wz_mini/usr/bin/iCamera

@@ -0,0 +1,5 @@
+#!/bin/sh
+
+set -x
+echo "inject callback library and run"
+LD_PRELOAD='libcallback.so:libtinyalsa.so.2.0.0:libsetunbuf.so' /run/.storage/iCamera