mirror of
https://github.com/motioneye-project/motioneyeos.git
synced 2025-07-27 21:26:36 +00:00
Merge pull request #2128 from popoviciri/mmal_rtsp_frontend
v4l2multi_stream_mmal low res mjpeg to frontend
This commit is contained in:
commit
5490d23d05
114
board/raspberrypi/motioneye-modules/streameyectl.py
Normal file → Executable file
114
board/raspberrypi/motioneye-modules/streameyectl.py
Normal file → Executable file
@ -412,9 +412,13 @@ def _get_streameye_settings(camera_id):
|
|||||||
'seProto': 'mjpeg',
|
'seProto': 'mjpeg',
|
||||||
'seAuthMode': 'disabled',
|
'seAuthMode': 'disabled',
|
||||||
'sePort': 8081,
|
'sePort': 8081,
|
||||||
'seRTSPPort': 554
|
'seRTSPPort': 554,
|
||||||
|
'seMJPEGWidth': 640,
|
||||||
|
'seMJPEGHeight': 480,
|
||||||
|
'seMJPEGFramerate': 5,
|
||||||
|
'seMJPEGBitrate': 800000
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.path.exists(STREAMEYE_CONF):
|
if os.path.exists(STREAMEYE_CONF):
|
||||||
logging.debug('reading streameye settings from %s' % STREAMEYE_CONF)
|
logging.debug('reading streameye settings from %s' % STREAMEYE_CONF)
|
||||||
|
|
||||||
@ -442,15 +446,40 @@ def _get_streameye_settings(camera_id):
|
|||||||
if m:
|
if m:
|
||||||
s['seProto'] = m[0]
|
s['seProto'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_WIDTH="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGWidth'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_HEIGHT="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGHeight'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_FRAMERATE="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGFramerate'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_BITRATE="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGBitrate'] = m[0]
|
||||||
|
|
||||||
|
s['seMJPEGRes'] = '%sx%s' % (s.pop('seMJPEGWidth'), s.pop('seMJPEGHeight'))
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def _set_streameye_settings(camera_id, s):
|
def _set_streameye_settings(camera_id, s):
|
||||||
s = dict(s)
|
s = dict(s)
|
||||||
|
s['seMJPEGWidth'] = int(s['seMJPEGRes'].split('x')[0])
|
||||||
|
s['seMJPEGHeight'] = int(s.pop('seMJPEGRes').split('x')[1])
|
||||||
|
|
||||||
s.setdefault('sePort', 8081)
|
s.setdefault('sePort', 8081)
|
||||||
s.setdefault('seRTSPPort', 554)
|
s.setdefault('seRTSPPort', 554)
|
||||||
s.setdefault('seAuthMode', 'disabled')
|
s.setdefault('seAuthMode', 'disabled')
|
||||||
|
s.setdefault('seMJPEGWidth', 640)
|
||||||
|
s.setdefault('seMJPEGHeight', 480)
|
||||||
|
s.setdefault('seMJPEGFramerate', 5)
|
||||||
|
s.setdefault('seMJPEGBitrate', 800000)
|
||||||
|
|
||||||
main_config = config.get_main()
|
main_config = config.get_main()
|
||||||
username = main_config['@normal_username']
|
username = main_config['@normal_username']
|
||||||
password = main_config['@normal_password']
|
password = main_config['@normal_password']
|
||||||
@ -462,6 +491,10 @@ def _set_streameye_settings(camera_id, s):
|
|||||||
'PROTO="%s"' % s['seProto'],
|
'PROTO="%s"' % s['seProto'],
|
||||||
'PORT="%s"' % s['sePort'],
|
'PORT="%s"' % s['sePort'],
|
||||||
'RTSP_PORT="%s"' % s['seRTSPPort'],
|
'RTSP_PORT="%s"' % s['seRTSPPort'],
|
||||||
|
'MJPEG_WIDTH="%s"' % s['seMJPEGWidth'],
|
||||||
|
'MJPEG_HEIGHT="%s"' % s['seMJPEGHeight'],
|
||||||
|
'MJPEG_FRAMERATE="%s"' % s['seMJPEGFramerate'],
|
||||||
|
'MJPEG_BITRATE="%s"' % s['seMJPEGBitrate'],
|
||||||
'AUTH="%s"' % s['seAuthMode'],
|
'AUTH="%s"' % s['seAuthMode'],
|
||||||
'CREDENTIALS="%s:%s:%s"' % (username, password, realm)
|
'CREDENTIALS="%s:%s:%s"' % (username, password, realm)
|
||||||
]
|
]
|
||||||
@ -1158,6 +1191,27 @@ def seProto():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seRTSPPort():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'Streaming RTSP Port',
|
||||||
|
'description': 'sets the TCP port on which the webcam streaming server listens',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 0,
|
||||||
|
'max': 65535,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@additional_config
|
@additional_config
|
||||||
def sePort():
|
def sePort():
|
||||||
if not _get_streameye_enabled():
|
if not _get_streameye_enabled():
|
||||||
@ -1172,7 +1226,6 @@ def sePort():
|
|||||||
'section': 'streaming',
|
'section': 'streaming',
|
||||||
'camera': True,
|
'camera': True,
|
||||||
'required': True,
|
'required': True,
|
||||||
'depends': ['seProto==mjpeg'],
|
|
||||||
'get': _get_streameye_settings,
|
'get': _get_streameye_settings,
|
||||||
'set': _set_streameye_settings,
|
'set': _set_streameye_settings,
|
||||||
'get_set_dict': True
|
'get_set_dict': True
|
||||||
@ -1180,16 +1233,60 @@ def sePort():
|
|||||||
|
|
||||||
|
|
||||||
@additional_config
|
@additional_config
|
||||||
def seRTSPPort():
|
def seMJPEGRes():
|
||||||
if not _get_streameye_enabled():
|
if not _get_streameye_enabled():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'label': 'Streaming Port',
|
'label': 'MJPEG Resolution',
|
||||||
'description': 'sets the TCP port on which the webcam streaming server listens',
|
'description': 'the MJPEG resolution fed to the frontend and used for motion detection on remote machines when streaming RTSP',
|
||||||
|
'type': 'choices',
|
||||||
|
'choices': RESOLUTION_CHOICES,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seMJPEGFramerate():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'MJPEG Frame Rate',
|
||||||
|
'description': 'the MJPEG Frame Rate fed to the frontend and used for motion detection on remote machines when streaming RTSP; for motion detection, 5 works good',
|
||||||
|
'type': 'range',
|
||||||
|
'min': 2,
|
||||||
|
'max': 30,
|
||||||
|
'snap': 0,
|
||||||
|
'ticks': "2|5|10|15|20|25|30",
|
||||||
|
'decimals': 0,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seMJPEGBitrate():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'MJPEG Bitrate',
|
||||||
|
'description': 'the MJPEG Bitrate fed to the frontend and used for motion detection on remote machines when streaming RTSP; for motion detection, 800000 works good',
|
||||||
'type': 'number',
|
'type': 'number',
|
||||||
'min': 0,
|
'min': 0,
|
||||||
'max': 65535,
|
'max': 25000000,
|
||||||
'section': 'streaming',
|
'section': 'streaming',
|
||||||
'camera': True,
|
'camera': True,
|
||||||
'required': True,
|
'required': True,
|
||||||
@ -1218,4 +1315,3 @@ def seAuthMode():
|
|||||||
'set': _set_streameye_settings,
|
'set': _set_streameye_settings,
|
||||||
'get_set_dict': True
|
'get_set_dict': True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
RASPIMJPEG_CONF=/data/etc/raspimjpeg.conf
|
RASPIMJPEG_CONF=/data/etc/raspimjpeg.conf
|
||||||
RASPIMJPEG_LOG=/var/log/raspimjpeg.log
|
RASPIMJPEG_LOG=/var/log/raspimjpeg.log
|
||||||
GSTREAMER_LOG=/var/log/gstreamer.log
|
RTSPSERVER_LOG=/var/log/rtspserver.log
|
||||||
MOTIONEYE_CONF=/data/etc/motioneye.conf
|
MOTIONEYE_CONF=/data/etc/motioneye.conf
|
||||||
STREAMEYE_CONF=/data/etc/streameye.conf
|
STREAMEYE_CONF=/data/etc/streameye.conf
|
||||||
STREAMEYE_LOG=/var/log/streameye.log
|
STREAMEYE_LOG=/var/log/streameye.log
|
||||||
@ -17,122 +17,22 @@ function watch() {
|
|||||||
while true; do
|
while true; do
|
||||||
sleep 5
|
sleep 5
|
||||||
if [ "${PROTO}" = "rtsp" ]; then
|
if [ "${PROTO}" = "rtsp" ]; then
|
||||||
if ! ps aux | grep test-launch | grep -v grep &>/dev/null; then
|
if ! ps aux | grep v4l2multi_stream_mmal | grep -v grep &>/dev/null; then
|
||||||
|
logger -t streameye -s "not running, respawning"
|
||||||
|
start
|
||||||
|
elif ! ps aux | grep v4l2rtspserver | grep -v grep &>/dev/null; then
|
||||||
logger -t streameye -s "not running, respawning"
|
logger -t streameye -s "not running, respawning"
|
||||||
start
|
start
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if ! ps aux | grep raspimjpeg.py | grep -v grep &>/dev/null; then
|
if ! ps aux | grep raspimjpeg.py | grep -v grep &>/dev/null; then
|
||||||
logger -t streameye -s "not running, respawning"
|
logger -t streameye -s "raspimjpeg.py not running, respawning"
|
||||||
start
|
start
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function configure_v4l2_cam() {
|
|
||||||
video_arg="-d $1"
|
|
||||||
|
|
||||||
horizontal_flip="0"
|
|
||||||
hflip=$(grep -e ^hflip ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${hflip}" = "true" ]; then horizontal_flip="1"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=horizontal_flip=${horizontal_flip} &>/dev/null
|
|
||||||
|
|
||||||
vertical_flip="0"
|
|
||||||
vflip=$(grep -e ^vflip ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${vflip}" = "true" ]; then vertical_flip="1"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=vertical_flip=${vertical_flip} &>/dev/null
|
|
||||||
|
|
||||||
rotate=$(grep -e ^rotation ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${rotate}" ]; then rotate="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=rotate=${rotate} &>/dev/null
|
|
||||||
|
|
||||||
brightness=$(grep -e ^brightness ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${brightness}" ]; then brightness="50"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=brightness=${brightness} &>/dev/null
|
|
||||||
|
|
||||||
contrast=$(grep -e ^contrast ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${contrast}" ]; then contrast="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=contrast=${contrast} &>/dev/null
|
|
||||||
|
|
||||||
saturation=$(grep -e ^saturation ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${saturation}" ]; then saturation="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=saturation=${saturation} &>/dev/null
|
|
||||||
|
|
||||||
sharpness=$(grep -e ^sharpness ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${sharpness}" ]; then sharpness="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=sharpness=${sharpness} &>/dev/null
|
|
||||||
|
|
||||||
vstab=$(grep -e ^vstab ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${vstab}" ]; then vstab="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=image_stabilization=${vstab} &>/dev/null
|
|
||||||
|
|
||||||
shutter=$(grep -e ^shutter ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${shutter}" ]; then shutter="0"; fi
|
|
||||||
if [ "${#shutter}" -gt 2 ]; then shutter=$(echo ${shutter/%??/}); else shutter="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=exposure_time_absolute=${shutter} &>/dev/null
|
|
||||||
|
|
||||||
iso=$(grep -e ^iso ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${iso}" ]; then iso="0"; fi
|
|
||||||
if [ "${iso}" -ge 800 ]; then iso="4"
|
|
||||||
elif [ "${iso}" -ge 400 ]; then iso="3"
|
|
||||||
elif [ "${iso}" -ge 200 ]; then iso="2"
|
|
||||||
elif [ "${iso}" -ge 100 ]; then iso="1"
|
|
||||||
else iso="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=iso_sensitivity=${iso} &>/dev/null
|
|
||||||
|
|
||||||
awb=$(grep -e ^awb ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${awb}" = "off" ]; then awb="0"
|
|
||||||
elif [ "${awb}" = "auto" ]; then awb="1"
|
|
||||||
elif [ "${awb}" = "sunlight" ]; then awb="6"
|
|
||||||
elif [ "${awb}" = "cloudy" ]; then awb="8"
|
|
||||||
elif [ "${awb}" = "shade" ]; then awb="9"
|
|
||||||
elif [ "${awb}" = "tungsten" ]; then awb="4"
|
|
||||||
elif [ "${awb}" = "fluorescent" ]; then awb="3"
|
|
||||||
elif [ "${awb}" = "incandescent" ]; then awb="2"
|
|
||||||
elif [ "${awb}" = "flash" ]; then awb="7"
|
|
||||||
elif [ "${awb}" = "horizon" ]; then awb="5"
|
|
||||||
else awb="1"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=white_balance_auto_preset=${awb} &>/dev/null
|
|
||||||
|
|
||||||
metering=$(grep -e ^metering ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${metering}" = "spot" ]; then metering="2"
|
|
||||||
elif [ "${metering}" = "center" ]; then metering="1"
|
|
||||||
else metering="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=exposure_metering_mode=${awb} &>/dev/null
|
|
||||||
|
|
||||||
scene="0"
|
|
||||||
exposure=$(grep -e ^exposure ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${exposure}" = "off" ]; then
|
|
||||||
exposure="1"
|
|
||||||
else
|
|
||||||
if [ "${exposure}" = "night" ]; then scene="8"
|
|
||||||
elif [ "${exposure}" = "backlight" ]; then scene="1"
|
|
||||||
elif [ "${exposure}" = "sports" ]; then scene="11"
|
|
||||||
elif [ "${exposure}" = "snow" ]; then scene="2"
|
|
||||||
elif [ "${exposure}" = "beach" ]; then scene="2"
|
|
||||||
elif [ "${exposure}" = "fireworks" ]; then scene="6"
|
|
||||||
fi
|
|
||||||
exposure="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=auto_exposure=${exposure} &>/dev/null
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=scene_mode=${scene} &>/dev/null
|
|
||||||
|
|
||||||
ev=$(grep -e ^ev ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${ev}" ]; then ev="0"; fi
|
|
||||||
ev=$(expr ${ev} + 25)
|
|
||||||
ev=$(expr ${ev} / 2)
|
|
||||||
if [ "${ev}" -gt 24 ]; then ev="24"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=auto_exposure_bias=${ev} &>/dev/null
|
|
||||||
|
|
||||||
video_bitrate=$(grep -e ^bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${video_bitrate}" ]; then video_bitrate="1000000"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=video_bitrate=${video_bitrate} &>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
function invalid_opt() {
|
function invalid_opt() {
|
||||||
local e match="$1"
|
local e match="$1"
|
||||||
shift
|
shift
|
||||||
@ -143,70 +43,106 @@ function invalid_opt() {
|
|||||||
function start() {
|
function start() {
|
||||||
source ${STREAMEYE_CONF}
|
source ${STREAMEYE_CONF}
|
||||||
streameye_opts="-p ${PORT}"
|
streameye_opts="-p ${PORT}"
|
||||||
|
rtspserver_opts=""
|
||||||
if [ -n "${CREDENTIALS}" ] && [ "${AUTH}" = "basic" ]; then
|
if [ -n "${CREDENTIALS}" ] && [ "${AUTH}" = "basic" ]; then
|
||||||
streameye_opts="${streameye_opts} -a basic -c ${CREDENTIALS}"
|
streameye_opts="${streameye_opts} -a basic -c ${CREDENTIALS}"
|
||||||
|
# TODO: Add RTSP Auth
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${PROTO}" = "rtsp" ]; then
|
if [ "${PROTO}" = "rtsp" ]; then
|
||||||
pid=$(ps | grep test-launch | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
v4l2rtspserver_pid=$(ps | grep v4l2rtspserver | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
if [ -n "${pid}" ]; then
|
v4l2multi_stream_mmal_pid=$(ps | grep v4l2multi_stream_mmal | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
return
|
if [ -n "${v4l2rtspserver_pid}" ]; then
|
||||||
|
if [ -n "${v4l2multi_stream_mmal_pid}" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RTSP_PORT=${RTSP_PORT:-554}
|
RTSP_PORT=${RTSP_PORT:-554}
|
||||||
|
MJPEG_WIDTH=${MJPEG_WIDTH:-640}
|
||||||
|
MJPEG_HEIGHT=${MJPEG_HEIGHT:-480}
|
||||||
|
MJPEG_FRAMERATE=${MJPEG_FRAMERATE:-5}
|
||||||
|
MJPEG_BITRATE=${MJPEG_BITRATE:-800000}
|
||||||
|
|
||||||
iptables -A INPUT -p tcp -s localhost --dport ${RTSP_PORT} -j ACCEPT
|
audio_path=""
|
||||||
iptables -A INPUT -p tcp --dport ${RTSP_PORT} -j DROP
|
|
||||||
|
|
||||||
audio_opts=""
|
audio_opts=""
|
||||||
if [ -n "${AUDIO_DEV}" ]; then
|
if [ -n "${AUDIO_DEV}" ]; then
|
||||||
|
audio_path=",${AUDIO_DEV}"
|
||||||
|
|
||||||
|
# Audio bitrate: default 44100
|
||||||
audio_bitrate=$(grep -e ^audio_bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
audio_bitrate=$(grep -e ^audio_bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
|
# Audio channels: default 2
|
||||||
audio_channels=$(grep -e ^audio_channels ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
audio_channels=$(grep -e ^audio_channels ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
audio_extras=""
|
# Valid audio formats: S16_BE, S16_LE, S24_BE, S24_LE, S32_BE, S32_LE, ALAW, MULAW, S8, MPEG
|
||||||
|
audio_format=$(grep -e ^audio_format ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
if [ -n "${audio_bitrate}" ]; then
|
if [ -n "${audio_bitrate}" ]; then
|
||||||
audio_extras="${audio_extras},rate=${audio_bitrate}"
|
audio_opts="${audio_opts} -A ${audio_bitrate}"
|
||||||
fi
|
fi
|
||||||
if [ -n "${audio_channels}" ]; then
|
if [ -n "${audio_channels}" ]; then
|
||||||
audio_extras="${audio_extras},channels=${audio_channels}"
|
audio_opts="${audio_opts} -C ${audio_channels}"
|
||||||
|
fi
|
||||||
|
if [ -n "${audio_format}" ]; then
|
||||||
|
audio_opts="${audio_opts} -a ${audio_format}"
|
||||||
fi
|
fi
|
||||||
audio_opts="alsasrc device=${AUDIO_DEV} ! audioresample ! audio/x-raw${audio_extras} ! queue ! voaacenc ! rtpmp4gpay pt=97 name=pay1"
|
|
||||||
fi
|
fi
|
||||||
video_path="/dev/video0"
|
# hardcode to 90 for now
|
||||||
if [ -n "${VIDEO_DEV}" ]; then
|
vidid=90
|
||||||
video_path=${VIDEO_DEV}
|
video_path="/dev/video${vidid}"
|
||||||
|
if lsmod | grep v4l2loopback &> /dev/null ; then
|
||||||
|
rmmod v4l2loopback
|
||||||
fi
|
fi
|
||||||
|
modprobe v4l2loopback video_nr=${vidid}
|
||||||
if [ -e "${video_path}" ]; then
|
if [ -e "${video_path}" ]; then
|
||||||
# Only configure camera if it is a Pi Cam
|
valid_opts=("analoggain" "awb" "awbgains" "bitrate" "brightness" "colfx" "contrast" "denoise" "digitalgain" "drc" "ev" "exposure" "flicker" "framerate" "height" "hflip" "imxfx" "intra" "irefresh" "level" "metering" "profile" "roi" "rotation" "saturation" "sharpness" "shutter" "vflip" "vstab" "width" "mjpegbitrate" "mjpegframerate" "mjpegwidth" "mjpegheight")
|
||||||
if v4l2-ctl -d ${video_path} -D | grep -q 'bm2835 mmal'; then
|
raspimjpeg_opts="--videoout ${video_path}"
|
||||||
configure_v4l2_cam ${video_path}
|
while read line; do
|
||||||
|
key=$(echo ${line} | cut -d ' ' -f 1)
|
||||||
|
if invalid_opt "${key}" "${valid_opts[@]}"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if echo "${line}" | grep false &>/dev/null; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if echo "${line}" | grep true &>/dev/null; then
|
||||||
|
line=${key}
|
||||||
|
fi
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --${line}"
|
||||||
|
done < ${RASPIMJPEG_CONF}
|
||||||
|
|
||||||
|
video_iso=$(grep -e ^iso ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
|
if [ -n "${video_iso}" ]; then
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --ISO ${video_iso}"
|
||||||
fi
|
fi
|
||||||
width=$(grep -e ^width ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
height=$(grep -e ^height ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
framerate=$(grep -e ^framerate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
video_extras=""
|
|
||||||
if [ -n "${width}" ]; then
|
|
||||||
video_extras="${video_extras},width=${width}"
|
|
||||||
fi
|
|
||||||
if [ -n "${height}" ]; then
|
|
||||||
video_extras="${video_extras},height=${height}"
|
|
||||||
fi
|
|
||||||
if [ -n "${framerate}" ]; then
|
|
||||||
video_extras="${video_extras},framerate=${framerate}/1"
|
|
||||||
fi
|
|
||||||
video_opts="v4l2src device=${video_path} ! video/x-h264${video_extras} ! h264parse ! rtph264pay name=pay0 pt=96"
|
|
||||||
|
|
||||||
if [ -r ${MOTIONEYE_CONF} ] && grep 'log-level debug' ${MOTIONEYE_CONF} >/dev/null; then
|
if [ -r ${MOTIONEYE_CONF} ] && grep 'log-level debug' ${MOTIONEYE_CONF} >/dev/null; then
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} -v"
|
||||||
streameye_opts="${streameye_opts} -d"
|
streameye_opts="${streameye_opts} -d"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test-launch -p ${RTSP_PORT} -m h264 "\"( ${video_opts} ${audio_opts} )\"" &>${GSTREAMER_LOG} &
|
rtspserver_opts="${rtspserver_opts} -P ${RTSP_PORT} -u h264"
|
||||||
sleep 10
|
video_framerate=$(grep -e ^framerate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
gst-launch-1.0 -v rtspsrc location=rtsp://127.0.0.1:${RTSP_PORT}/h264 latency=0 drop-on-latency=1 ! rtph264depay ! h264parse ! omxh264dec ! videorate ! video/x-raw,framerate=5/1 ! jpegenc ! filesink location=/dev/stdout | streameye ${streameye_opts} &>${STREAMEYE_LOG} &
|
video_intra=$(grep -e ^intra ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
sleep 5
|
if [ -n "${video_framerate}" ]; then
|
||||||
fi
|
rtspserver_opts="${rtspserver_opts} -F ${video_framerate}"
|
||||||
|
if [ -z "${video_intra}" ]; then
|
||||||
|
let "video_intra=$((video_framerate))*2"
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --intra ${video_intra}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
iptables -D INPUT -p tcp --dport ${RTSP_PORT} -j DROP
|
mjpeg_opts="--mjpegbitrate ${MJPEG_BITRATE} --mjpegwidth ${MJPEG_WIDTH} --mjpegheight ${MJPEG_HEIGHT} --mjpegframerate ${MJPEG_FRAMERATE}"
|
||||||
iptables -D INPUT -p tcp -s localhost --dport ${RTSP_PORT} -j ACCEPT
|
raspimjpeg_opts="${raspimjpeg_opts} ${mjpeg_opts}"
|
||||||
|
|
||||||
|
if [ -z "${v4l2multi_stream_mmal_pid}" ]; then
|
||||||
|
v4l2multi_stream_mmal -v ${raspimjpeg_opts} -o - 2>${RTSPSERVER_LOG} | streameye ${streameye_opts} &>${STREAMEYE_LOG} &
|
||||||
|
sleep 10
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${v4l2rtspserver_pid}" ]; then
|
||||||
|
v4l2rtspserver ${rtspserver_opts} ${audio_opts} ${video_path}${audio_path} &>${RTSPSERVER_LOG} &
|
||||||
|
sleep 5
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
@ -244,41 +180,25 @@ function stop() {
|
|||||||
# stop the streameye background watch process
|
# stop the streameye background watch process
|
||||||
ps | grep streameye.sh | grep -v $$ | grep -v S94streameye| grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
ps | grep streameye.sh | grep -v $$ | grep -v S94streameye| grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
||||||
|
|
||||||
# stop the raspimjpeg process
|
# stop the running streaming process
|
||||||
raspimjpeg_pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
processes=( "raspimjpeg.py" "v4l2rtspserver" "v4l2multi_stream_mmal" )
|
||||||
# stop the gst-launch-1.0 process
|
for i in "${processes[@]}"
|
||||||
gst_launch_pid=$(ps | grep gst-launch-1.0 | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
do
|
||||||
# stop the test-launch process
|
pid=$(ps | grep $i | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
test_launch_pid=$(ps | grep test-launch | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
if [ -n "${pid}" ]; then
|
||||||
|
kill -HUP "${pid}" &>/dev/null
|
||||||
|
count=0
|
||||||
|
while kill -0 "${pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
||||||
|
sleep 1
|
||||||
|
count=$((${count} + 1))
|
||||||
|
done
|
||||||
|
kill -KILL "${pid}" &>/dev/null || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
if [ -n "${raspimjpeg_pid}" ]; then
|
# stop the loopback device
|
||||||
kill -HUP "${raspimjpeg_pid}" &>/dev/null
|
if lsmod | grep v4l2loopback &> /dev/null ; then
|
||||||
count=0
|
rmmod v4l2loopback
|
||||||
while kill -0 "${raspimjpeg_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${raspimjpeg_pid}" &>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${gst_launch_pid}" ]; then
|
|
||||||
kill -HUP "${gst_launch_pid}" &>/dev/null
|
|
||||||
count=0
|
|
||||||
while kill -0 "${gst_launch_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${gst_launch_pid}" &>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${test_launch_pid}" ]; then
|
|
||||||
kill -HUP "${test_launch_pid}" &>/dev/null
|
|
||||||
count=0
|
|
||||||
while kill -0 "${test_launch_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${test_launch_pid}" &>/dev/null || true
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,4 +222,3 @@ case "$1" in
|
|||||||
echo $"Usage: $0 {start|stop|restart}"
|
echo $"Usage: $0 {start|stop|restart}"
|
||||||
exit 1
|
exit 1
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
114
board/raspberrypi2/motioneye-modules/streameyectl.py
Normal file → Executable file
114
board/raspberrypi2/motioneye-modules/streameyectl.py
Normal file → Executable file
@ -412,9 +412,13 @@ def _get_streameye_settings(camera_id):
|
|||||||
'seProto': 'mjpeg',
|
'seProto': 'mjpeg',
|
||||||
'seAuthMode': 'disabled',
|
'seAuthMode': 'disabled',
|
||||||
'sePort': 8081,
|
'sePort': 8081,
|
||||||
'seRTSPPort': 554
|
'seRTSPPort': 554,
|
||||||
|
'seMJPEGWidth': 640,
|
||||||
|
'seMJPEGHeight': 480,
|
||||||
|
'seMJPEGFramerate': 5,
|
||||||
|
'seMJPEGBitrate': 800000
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.path.exists(STREAMEYE_CONF):
|
if os.path.exists(STREAMEYE_CONF):
|
||||||
logging.debug('reading streameye settings from %s' % STREAMEYE_CONF)
|
logging.debug('reading streameye settings from %s' % STREAMEYE_CONF)
|
||||||
|
|
||||||
@ -442,15 +446,40 @@ def _get_streameye_settings(camera_id):
|
|||||||
if m:
|
if m:
|
||||||
s['seProto'] = m[0]
|
s['seProto'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_WIDTH="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGWidth'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_HEIGHT="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGHeight'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_FRAMERATE="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGFramerate'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_BITRATE="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGBitrate'] = m[0]
|
||||||
|
|
||||||
|
s['seMJPEGRes'] = '%sx%s' % (s.pop('seMJPEGWidth'), s.pop('seMJPEGHeight'))
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def _set_streameye_settings(camera_id, s):
|
def _set_streameye_settings(camera_id, s):
|
||||||
s = dict(s)
|
s = dict(s)
|
||||||
|
s['seMJPEGWidth'] = int(s['seMJPEGRes'].split('x')[0])
|
||||||
|
s['seMJPEGHeight'] = int(s.pop('seMJPEGRes').split('x')[1])
|
||||||
|
|
||||||
s.setdefault('sePort', 8081)
|
s.setdefault('sePort', 8081)
|
||||||
s.setdefault('seRTSPPort', 554)
|
s.setdefault('seRTSPPort', 554)
|
||||||
s.setdefault('seAuthMode', 'disabled')
|
s.setdefault('seAuthMode', 'disabled')
|
||||||
|
s.setdefault('seMJPEGWidth', 640)
|
||||||
|
s.setdefault('seMJPEGHeight', 480)
|
||||||
|
s.setdefault('seMJPEGFramerate', 5)
|
||||||
|
s.setdefault('seMJPEGBitrate', 800000)
|
||||||
|
|
||||||
main_config = config.get_main()
|
main_config = config.get_main()
|
||||||
username = main_config['@normal_username']
|
username = main_config['@normal_username']
|
||||||
password = main_config['@normal_password']
|
password = main_config['@normal_password']
|
||||||
@ -462,6 +491,10 @@ def _set_streameye_settings(camera_id, s):
|
|||||||
'PROTO="%s"' % s['seProto'],
|
'PROTO="%s"' % s['seProto'],
|
||||||
'PORT="%s"' % s['sePort'],
|
'PORT="%s"' % s['sePort'],
|
||||||
'RTSP_PORT="%s"' % s['seRTSPPort'],
|
'RTSP_PORT="%s"' % s['seRTSPPort'],
|
||||||
|
'MJPEG_WIDTH="%s"' % s['seMJPEGWidth'],
|
||||||
|
'MJPEG_HEIGHT="%s"' % s['seMJPEGHeight'],
|
||||||
|
'MJPEG_FRAMERATE="%s"' % s['seMJPEGFramerate'],
|
||||||
|
'MJPEG_BITRATE="%s"' % s['seMJPEGBitrate'],
|
||||||
'AUTH="%s"' % s['seAuthMode'],
|
'AUTH="%s"' % s['seAuthMode'],
|
||||||
'CREDENTIALS="%s:%s:%s"' % (username, password, realm)
|
'CREDENTIALS="%s:%s:%s"' % (username, password, realm)
|
||||||
]
|
]
|
||||||
@ -1158,6 +1191,27 @@ def seProto():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seRTSPPort():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'Streaming RTSP Port',
|
||||||
|
'description': 'sets the TCP port on which the webcam streaming server listens',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 0,
|
||||||
|
'max': 65535,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@additional_config
|
@additional_config
|
||||||
def sePort():
|
def sePort():
|
||||||
if not _get_streameye_enabled():
|
if not _get_streameye_enabled():
|
||||||
@ -1172,7 +1226,6 @@ def sePort():
|
|||||||
'section': 'streaming',
|
'section': 'streaming',
|
||||||
'camera': True,
|
'camera': True,
|
||||||
'required': True,
|
'required': True,
|
||||||
'depends': ['seProto==mjpeg'],
|
|
||||||
'get': _get_streameye_settings,
|
'get': _get_streameye_settings,
|
||||||
'set': _set_streameye_settings,
|
'set': _set_streameye_settings,
|
||||||
'get_set_dict': True
|
'get_set_dict': True
|
||||||
@ -1180,16 +1233,60 @@ def sePort():
|
|||||||
|
|
||||||
|
|
||||||
@additional_config
|
@additional_config
|
||||||
def seRTSPPort():
|
def seMJPEGRes():
|
||||||
if not _get_streameye_enabled():
|
if not _get_streameye_enabled():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'label': 'Streaming Port',
|
'label': 'MJPEG Resolution',
|
||||||
'description': 'sets the TCP port on which the webcam streaming server listens',
|
'description': 'the MJPEG resolution fed to the frontend and used for motion detection on remote machines when streaming RTSP',
|
||||||
|
'type': 'choices',
|
||||||
|
'choices': RESOLUTION_CHOICES,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seMJPEGFramerate():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'MJPEG Frame Rate',
|
||||||
|
'description': 'the MJPEG Frame Rate fed to the frontend and used for motion detection on remote machines when streaming RTSP; for motion detection, 5 works good',
|
||||||
|
'type': 'range',
|
||||||
|
'min': 2,
|
||||||
|
'max': 30,
|
||||||
|
'snap': 0,
|
||||||
|
'ticks': "2|5|10|15|20|25|30",
|
||||||
|
'decimals': 0,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seMJPEGBitrate():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'MJPEG Bitrate',
|
||||||
|
'description': 'the MJPEG Bitrate fed to the frontend and used for motion detection on remote machines when streaming RTSP; for motion detection, 800000 works good',
|
||||||
'type': 'number',
|
'type': 'number',
|
||||||
'min': 0,
|
'min': 0,
|
||||||
'max': 65535,
|
'max': 25000000,
|
||||||
'section': 'streaming',
|
'section': 'streaming',
|
||||||
'camera': True,
|
'camera': True,
|
||||||
'required': True,
|
'required': True,
|
||||||
@ -1218,4 +1315,3 @@ def seAuthMode():
|
|||||||
'set': _set_streameye_settings,
|
'set': _set_streameye_settings,
|
||||||
'get_set_dict': True
|
'get_set_dict': True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
RASPIMJPEG_CONF=/data/etc/raspimjpeg.conf
|
RASPIMJPEG_CONF=/data/etc/raspimjpeg.conf
|
||||||
RASPIMJPEG_LOG=/var/log/raspimjpeg.log
|
RASPIMJPEG_LOG=/var/log/raspimjpeg.log
|
||||||
GSTREAMER_LOG=/var/log/gstreamer.log
|
RTSPSERVER_LOG=/var/log/rtspserver.log
|
||||||
MOTIONEYE_CONF=/data/etc/motioneye.conf
|
MOTIONEYE_CONF=/data/etc/motioneye.conf
|
||||||
STREAMEYE_CONF=/data/etc/streameye.conf
|
STREAMEYE_CONF=/data/etc/streameye.conf
|
||||||
STREAMEYE_LOG=/var/log/streameye.log
|
STREAMEYE_LOG=/var/log/streameye.log
|
||||||
@ -17,122 +17,22 @@ function watch() {
|
|||||||
while true; do
|
while true; do
|
||||||
sleep 5
|
sleep 5
|
||||||
if [ "${PROTO}" = "rtsp" ]; then
|
if [ "${PROTO}" = "rtsp" ]; then
|
||||||
if ! ps aux | grep test-launch | grep -v grep &>/dev/null; then
|
if ! ps aux | grep v4l2multi_stream_mmal | grep -v grep &>/dev/null; then
|
||||||
|
logger -t streameye -s "not running, respawning"
|
||||||
|
start
|
||||||
|
elif ! ps aux | grep v4l2rtspserver | grep -v grep &>/dev/null; then
|
||||||
logger -t streameye -s "not running, respawning"
|
logger -t streameye -s "not running, respawning"
|
||||||
start
|
start
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if ! ps aux | grep raspimjpeg.py | grep -v grep &>/dev/null; then
|
if ! ps aux | grep raspimjpeg.py | grep -v grep &>/dev/null; then
|
||||||
logger -t streameye -s "not running, respawning"
|
logger -t streameye -s "raspimjpeg.py not running, respawning"
|
||||||
start
|
start
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function configure_v4l2_cam() {
|
|
||||||
video_arg="-d $1"
|
|
||||||
|
|
||||||
horizontal_flip="0"
|
|
||||||
hflip=$(grep -e ^hflip ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${hflip}" = "true" ]; then horizontal_flip="1"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=horizontal_flip=${horizontal_flip} &>/dev/null
|
|
||||||
|
|
||||||
vertical_flip="0"
|
|
||||||
vflip=$(grep -e ^vflip ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${vflip}" = "true" ]; then vertical_flip="1"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=vertical_flip=${vertical_flip} &>/dev/null
|
|
||||||
|
|
||||||
rotate=$(grep -e ^rotation ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${rotate}" ]; then rotate="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=rotate=${rotate} &>/dev/null
|
|
||||||
|
|
||||||
brightness=$(grep -e ^brightness ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${brightness}" ]; then brightness="50"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=brightness=${brightness} &>/dev/null
|
|
||||||
|
|
||||||
contrast=$(grep -e ^contrast ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${contrast}" ]; then contrast="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=contrast=${contrast} &>/dev/null
|
|
||||||
|
|
||||||
saturation=$(grep -e ^saturation ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${saturation}" ]; then saturation="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=saturation=${saturation} &>/dev/null
|
|
||||||
|
|
||||||
sharpness=$(grep -e ^sharpness ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${sharpness}" ]; then sharpness="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=sharpness=${sharpness} &>/dev/null
|
|
||||||
|
|
||||||
vstab=$(grep -e ^vstab ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${vstab}" ]; then vstab="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=image_stabilization=${vstab} &>/dev/null
|
|
||||||
|
|
||||||
shutter=$(grep -e ^shutter ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${shutter}" ]; then shutter="0"; fi
|
|
||||||
if [ "${#shutter}" -gt 2 ]; then shutter=$(echo ${shutter/%??/}); else shutter="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=exposure_time_absolute=${shutter} &>/dev/null
|
|
||||||
|
|
||||||
iso=$(grep -e ^iso ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${iso}" ]; then iso="0"; fi
|
|
||||||
if [ "${iso}" -ge 800 ]; then iso="4"
|
|
||||||
elif [ "${iso}" -ge 400 ]; then iso="3"
|
|
||||||
elif [ "${iso}" -ge 200 ]; then iso="2"
|
|
||||||
elif [ "${iso}" -ge 100 ]; then iso="1"
|
|
||||||
else iso="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=iso_sensitivity=${iso} &>/dev/null
|
|
||||||
|
|
||||||
awb=$(grep -e ^awb ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${awb}" = "off" ]; then awb="0"
|
|
||||||
elif [ "${awb}" = "auto" ]; then awb="1"
|
|
||||||
elif [ "${awb}" = "sunlight" ]; then awb="6"
|
|
||||||
elif [ "${awb}" = "cloudy" ]; then awb="8"
|
|
||||||
elif [ "${awb}" = "shade" ]; then awb="9"
|
|
||||||
elif [ "${awb}" = "tungsten" ]; then awb="4"
|
|
||||||
elif [ "${awb}" = "fluorescent" ]; then awb="3"
|
|
||||||
elif [ "${awb}" = "incandescent" ]; then awb="2"
|
|
||||||
elif [ "${awb}" = "flash" ]; then awb="7"
|
|
||||||
elif [ "${awb}" = "horizon" ]; then awb="5"
|
|
||||||
else awb="1"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=white_balance_auto_preset=${awb} &>/dev/null
|
|
||||||
|
|
||||||
metering=$(grep -e ^metering ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${metering}" = "spot" ]; then metering="2"
|
|
||||||
elif [ "${metering}" = "center" ]; then metering="1"
|
|
||||||
else metering="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=exposure_metering_mode=${awb} &>/dev/null
|
|
||||||
|
|
||||||
scene="0"
|
|
||||||
exposure=$(grep -e ^exposure ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${exposure}" = "off" ]; then
|
|
||||||
exposure="1"
|
|
||||||
else
|
|
||||||
if [ "${exposure}" = "night" ]; then scene="8"
|
|
||||||
elif [ "${exposure}" = "backlight" ]; then scene="1"
|
|
||||||
elif [ "${exposure}" = "sports" ]; then scene="11"
|
|
||||||
elif [ "${exposure}" = "snow" ]; then scene="2"
|
|
||||||
elif [ "${exposure}" = "beach" ]; then scene="2"
|
|
||||||
elif [ "${exposure}" = "fireworks" ]; then scene="6"
|
|
||||||
fi
|
|
||||||
exposure="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=auto_exposure=${exposure} &>/dev/null
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=scene_mode=${scene} &>/dev/null
|
|
||||||
|
|
||||||
ev=$(grep -e ^ev ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${ev}" ]; then ev="0"; fi
|
|
||||||
ev=$(expr ${ev} + 25)
|
|
||||||
ev=$(expr ${ev} / 2)
|
|
||||||
if [ "${ev}" -gt 24 ]; then ev="24"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=auto_exposure_bias=${ev} &>/dev/null
|
|
||||||
|
|
||||||
video_bitrate=$(grep -e ^bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${video_bitrate}" ]; then video_bitrate="1000000"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=video_bitrate=${video_bitrate} &>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
function invalid_opt() {
|
function invalid_opt() {
|
||||||
local e match="$1"
|
local e match="$1"
|
||||||
shift
|
shift
|
||||||
@ -143,70 +43,106 @@ function invalid_opt() {
|
|||||||
function start() {
|
function start() {
|
||||||
source ${STREAMEYE_CONF}
|
source ${STREAMEYE_CONF}
|
||||||
streameye_opts="-p ${PORT}"
|
streameye_opts="-p ${PORT}"
|
||||||
|
rtspserver_opts=""
|
||||||
if [ -n "${CREDENTIALS}" ] && [ "${AUTH}" = "basic" ]; then
|
if [ -n "${CREDENTIALS}" ] && [ "${AUTH}" = "basic" ]; then
|
||||||
streameye_opts="${streameye_opts} -a basic -c ${CREDENTIALS}"
|
streameye_opts="${streameye_opts} -a basic -c ${CREDENTIALS}"
|
||||||
|
# TODO: Add RTSP Auth
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${PROTO}" = "rtsp" ]; then
|
if [ "${PROTO}" = "rtsp" ]; then
|
||||||
pid=$(ps | grep test-launch | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
v4l2rtspserver_pid=$(ps | grep v4l2rtspserver | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
if [ -n "${pid}" ]; then
|
v4l2multi_stream_mmal_pid=$(ps | grep v4l2multi_stream_mmal | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
return
|
if [ -n "${v4l2rtspserver_pid}" ]; then
|
||||||
|
if [ -n "${v4l2multi_stream_mmal_pid}" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RTSP_PORT=${RTSP_PORT:-554}
|
RTSP_PORT=${RTSP_PORT:-554}
|
||||||
|
MJPEG_WIDTH=${MJPEG_WIDTH:-640}
|
||||||
|
MJPEG_HEIGHT=${MJPEG_HEIGHT:-480}
|
||||||
|
MJPEG_FRAMERATE=${MJPEG_FRAMERATE:-5}
|
||||||
|
MJPEG_BITRATE=${MJPEG_BITRATE:-800000}
|
||||||
|
|
||||||
iptables -A INPUT -p tcp -s localhost --dport ${RTSP_PORT} -j ACCEPT
|
audio_path=""
|
||||||
iptables -A INPUT -p tcp --dport ${RTSP_PORT} -j DROP
|
|
||||||
|
|
||||||
audio_opts=""
|
audio_opts=""
|
||||||
if [ -n "${AUDIO_DEV}" ]; then
|
if [ -n "${AUDIO_DEV}" ]; then
|
||||||
|
audio_path=",${AUDIO_DEV}"
|
||||||
|
|
||||||
|
# Audio bitrate: default 44100
|
||||||
audio_bitrate=$(grep -e ^audio_bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
audio_bitrate=$(grep -e ^audio_bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
|
# Audio channels: default 2
|
||||||
audio_channels=$(grep -e ^audio_channels ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
audio_channels=$(grep -e ^audio_channels ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
audio_extras=""
|
# Valid audio formats: S16_BE, S16_LE, S24_BE, S24_LE, S32_BE, S32_LE, ALAW, MULAW, S8, MPEG
|
||||||
|
audio_format=$(grep -e ^audio_format ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
if [ -n "${audio_bitrate}" ]; then
|
if [ -n "${audio_bitrate}" ]; then
|
||||||
audio_extras="${audio_extras},rate=${audio_bitrate}"
|
audio_opts="${audio_opts} -A ${audio_bitrate}"
|
||||||
fi
|
fi
|
||||||
if [ -n "${audio_channels}" ]; then
|
if [ -n "${audio_channels}" ]; then
|
||||||
audio_extras="${audio_extras},channels=${audio_channels}"
|
audio_opts="${audio_opts} -C ${audio_channels}"
|
||||||
|
fi
|
||||||
|
if [ -n "${audio_format}" ]; then
|
||||||
|
audio_opts="${audio_opts} -a ${audio_format}"
|
||||||
fi
|
fi
|
||||||
audio_opts="alsasrc device=${AUDIO_DEV} ! audioresample ! audio/x-raw${audio_extras} ! queue ! voaacenc ! rtpmp4gpay pt=97 name=pay1"
|
|
||||||
fi
|
fi
|
||||||
video_path="/dev/video0"
|
# hardcode to 90 for now
|
||||||
if [ -n "${VIDEO_DEV}" ]; then
|
vidid=90
|
||||||
video_path=${VIDEO_DEV}
|
video_path="/dev/video${vidid}"
|
||||||
|
if lsmod | grep v4l2loopback &> /dev/null ; then
|
||||||
|
rmmod v4l2loopback
|
||||||
fi
|
fi
|
||||||
|
modprobe v4l2loopback video_nr=${vidid}
|
||||||
if [ -e "${video_path}" ]; then
|
if [ -e "${video_path}" ]; then
|
||||||
# Only configure camera if it is a Pi Cam
|
valid_opts=("analoggain" "awb" "awbgains" "bitrate" "brightness" "colfx" "contrast" "denoise" "digitalgain" "drc" "ev" "exposure" "flicker" "framerate" "height" "hflip" "imxfx" "intra" "irefresh" "level" "metering" "profile" "roi" "rotation" "saturation" "sharpness" "shutter" "vflip" "vstab" "width" "mjpegbitrate" "mjpegframerate" "mjpegwidth" "mjpegheight")
|
||||||
if v4l2-ctl -d ${video_path} -D | grep -q 'bm2835 mmal'; then
|
raspimjpeg_opts="--videoout ${video_path}"
|
||||||
configure_v4l2_cam ${video_path}
|
while read line; do
|
||||||
|
key=$(echo ${line} | cut -d ' ' -f 1)
|
||||||
|
if invalid_opt "${key}" "${valid_opts[@]}"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if echo "${line}" | grep false &>/dev/null; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if echo "${line}" | grep true &>/dev/null; then
|
||||||
|
line=${key}
|
||||||
|
fi
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --${line}"
|
||||||
|
done < ${RASPIMJPEG_CONF}
|
||||||
|
|
||||||
|
video_iso=$(grep -e ^iso ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
|
if [ -n "${video_iso}" ]; then
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --ISO ${video_iso}"
|
||||||
fi
|
fi
|
||||||
width=$(grep -e ^width ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
height=$(grep -e ^height ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
framerate=$(grep -e ^framerate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
video_extras=""
|
|
||||||
if [ -n "${width}" ]; then
|
|
||||||
video_extras="${video_extras},width=${width}"
|
|
||||||
fi
|
|
||||||
if [ -n "${height}" ]; then
|
|
||||||
video_extras="${video_extras},height=${height}"
|
|
||||||
fi
|
|
||||||
if [ -n "${framerate}" ]; then
|
|
||||||
video_extras="${video_extras},framerate=${framerate}/1"
|
|
||||||
fi
|
|
||||||
video_opts="v4l2src device=${video_path} ! video/x-h264${video_extras} ! h264parse ! rtph264pay name=pay0 pt=96"
|
|
||||||
|
|
||||||
if [ -r ${MOTIONEYE_CONF} ] && grep 'log-level debug' ${MOTIONEYE_CONF} >/dev/null; then
|
if [ -r ${MOTIONEYE_CONF} ] && grep 'log-level debug' ${MOTIONEYE_CONF} >/dev/null; then
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} -v"
|
||||||
streameye_opts="${streameye_opts} -d"
|
streameye_opts="${streameye_opts} -d"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test-launch -p ${RTSP_PORT} -m h264 "\"( ${video_opts} ${audio_opts} )\"" &>${GSTREAMER_LOG} &
|
rtspserver_opts="${rtspserver_opts} -P ${RTSP_PORT} -u h264"
|
||||||
sleep 10
|
video_framerate=$(grep -e ^framerate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
gst-launch-1.0 -v rtspsrc location=rtsp://127.0.0.1:${RTSP_PORT}/h264 latency=0 drop-on-latency=1 ! rtph264depay ! h264parse ! omxh264dec ! videorate ! video/x-raw,framerate=5/1 ! jpegenc ! filesink location=/dev/stdout | streameye ${streameye_opts} &>${STREAMEYE_LOG} &
|
video_intra=$(grep -e ^intra ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
sleep 5
|
if [ -n "${video_framerate}" ]; then
|
||||||
fi
|
rtspserver_opts="${rtspserver_opts} -F ${video_framerate}"
|
||||||
|
if [ -z "${video_intra}" ]; then
|
||||||
|
let "video_intra=$((video_framerate))*2"
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --intra ${video_intra}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
iptables -D INPUT -p tcp --dport ${RTSP_PORT} -j DROP
|
mjpeg_opts="--mjpegbitrate ${MJPEG_BITRATE} --mjpegwidth ${MJPEG_WIDTH} --mjpegheight ${MJPEG_HEIGHT} --mjpegframerate ${MJPEG_FRAMERATE}"
|
||||||
iptables -D INPUT -p tcp -s localhost --dport ${RTSP_PORT} -j ACCEPT
|
raspimjpeg_opts="${raspimjpeg_opts} ${mjpeg_opts}"
|
||||||
|
|
||||||
|
if [ -z "${v4l2multi_stream_mmal_pid}" ]; then
|
||||||
|
v4l2multi_stream_mmal -v ${raspimjpeg_opts} -o - 2>${RTSPSERVER_LOG} | streameye ${streameye_opts} &>${STREAMEYE_LOG} &
|
||||||
|
sleep 10
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${v4l2rtspserver_pid}" ]; then
|
||||||
|
v4l2rtspserver ${rtspserver_opts} ${audio_opts} ${video_path}${audio_path} &>${RTSPSERVER_LOG} &
|
||||||
|
sleep 5
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
@ -244,41 +180,25 @@ function stop() {
|
|||||||
# stop the streameye background watch process
|
# stop the streameye background watch process
|
||||||
ps | grep streameye.sh | grep -v $$ | grep -v S94streameye| grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
ps | grep streameye.sh | grep -v $$ | grep -v S94streameye| grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
||||||
|
|
||||||
# stop the raspimjpeg process
|
# stop the running streaming process
|
||||||
raspimjpeg_pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
processes=( "raspimjpeg.py" "v4l2rtspserver" "v4l2multi_stream_mmal" )
|
||||||
# stop the gst-launch-1.0 process
|
for i in "${processes[@]}"
|
||||||
gst_launch_pid=$(ps | grep gst-launch-1.0 | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
do
|
||||||
# stop the test-launch process
|
pid=$(ps | grep $i | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
test_launch_pid=$(ps | grep test-launch | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
if [ -n "${pid}" ]; then
|
||||||
|
kill -HUP "${pid}" &>/dev/null
|
||||||
|
count=0
|
||||||
|
while kill -0 "${pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
||||||
|
sleep 1
|
||||||
|
count=$((${count} + 1))
|
||||||
|
done
|
||||||
|
kill -KILL "${pid}" &>/dev/null || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
if [ -n "${raspimjpeg_pid}" ]; then
|
# stop the loopback device
|
||||||
kill -HUP "${raspimjpeg_pid}" &>/dev/null
|
if lsmod | grep v4l2loopback &> /dev/null ; then
|
||||||
count=0
|
rmmod v4l2loopback
|
||||||
while kill -0 "${raspimjpeg_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${raspimjpeg_pid}" &>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${gst_launch_pid}" ]; then
|
|
||||||
kill -HUP "${gst_launch_pid}" &>/dev/null
|
|
||||||
count=0
|
|
||||||
while kill -0 "${gst_launch_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${gst_launch_pid}" &>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${test_launch_pid}" ]; then
|
|
||||||
kill -HUP "${test_launch_pid}" &>/dev/null
|
|
||||||
count=0
|
|
||||||
while kill -0 "${test_launch_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${test_launch_pid}" &>/dev/null || true
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,4 +222,3 @@ case "$1" in
|
|||||||
echo $"Usage: $0 {start|stop|restart}"
|
echo $"Usage: $0 {start|stop|restart}"
|
||||||
exit 1
|
exit 1
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
114
board/raspberrypi3/motioneye-modules/streameyectl.py
Normal file → Executable file
114
board/raspberrypi3/motioneye-modules/streameyectl.py
Normal file → Executable file
@ -412,9 +412,13 @@ def _get_streameye_settings(camera_id):
|
|||||||
'seProto': 'mjpeg',
|
'seProto': 'mjpeg',
|
||||||
'seAuthMode': 'disabled',
|
'seAuthMode': 'disabled',
|
||||||
'sePort': 8081,
|
'sePort': 8081,
|
||||||
'seRTSPPort': 554
|
'seRTSPPort': 554,
|
||||||
|
'seMJPEGWidth': 640,
|
||||||
|
'seMJPEGHeight': 480,
|
||||||
|
'seMJPEGFramerate': 5,
|
||||||
|
'seMJPEGBitrate': 800000
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.path.exists(STREAMEYE_CONF):
|
if os.path.exists(STREAMEYE_CONF):
|
||||||
logging.debug('reading streameye settings from %s' % STREAMEYE_CONF)
|
logging.debug('reading streameye settings from %s' % STREAMEYE_CONF)
|
||||||
|
|
||||||
@ -442,15 +446,40 @@ def _get_streameye_settings(camera_id):
|
|||||||
if m:
|
if m:
|
||||||
s['seProto'] = m[0]
|
s['seProto'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_WIDTH="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGWidth'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_HEIGHT="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGHeight'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_FRAMERATE="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGFramerate'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_BITRATE="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGBitrate'] = m[0]
|
||||||
|
|
||||||
|
s['seMJPEGRes'] = '%sx%s' % (s.pop('seMJPEGWidth'), s.pop('seMJPEGHeight'))
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def _set_streameye_settings(camera_id, s):
|
def _set_streameye_settings(camera_id, s):
|
||||||
s = dict(s)
|
s = dict(s)
|
||||||
|
s['seMJPEGWidth'] = int(s['seMJPEGRes'].split('x')[0])
|
||||||
|
s['seMJPEGHeight'] = int(s.pop('seMJPEGRes').split('x')[1])
|
||||||
|
|
||||||
s.setdefault('sePort', 8081)
|
s.setdefault('sePort', 8081)
|
||||||
s.setdefault('seRTSPPort', 554)
|
s.setdefault('seRTSPPort', 554)
|
||||||
s.setdefault('seAuthMode', 'disabled')
|
s.setdefault('seAuthMode', 'disabled')
|
||||||
|
s.setdefault('seMJPEGWidth', 640)
|
||||||
|
s.setdefault('seMJPEGHeight', 480)
|
||||||
|
s.setdefault('seMJPEGFramerate', 5)
|
||||||
|
s.setdefault('seMJPEGBitrate', 800000)
|
||||||
|
|
||||||
main_config = config.get_main()
|
main_config = config.get_main()
|
||||||
username = main_config['@normal_username']
|
username = main_config['@normal_username']
|
||||||
password = main_config['@normal_password']
|
password = main_config['@normal_password']
|
||||||
@ -462,6 +491,10 @@ def _set_streameye_settings(camera_id, s):
|
|||||||
'PROTO="%s"' % s['seProto'],
|
'PROTO="%s"' % s['seProto'],
|
||||||
'PORT="%s"' % s['sePort'],
|
'PORT="%s"' % s['sePort'],
|
||||||
'RTSP_PORT="%s"' % s['seRTSPPort'],
|
'RTSP_PORT="%s"' % s['seRTSPPort'],
|
||||||
|
'MJPEG_WIDTH="%s"' % s['seMJPEGWidth'],
|
||||||
|
'MJPEG_HEIGHT="%s"' % s['seMJPEGHeight'],
|
||||||
|
'MJPEG_FRAMERATE="%s"' % s['seMJPEGFramerate'],
|
||||||
|
'MJPEG_BITRATE="%s"' % s['seMJPEGBitrate'],
|
||||||
'AUTH="%s"' % s['seAuthMode'],
|
'AUTH="%s"' % s['seAuthMode'],
|
||||||
'CREDENTIALS="%s:%s:%s"' % (username, password, realm)
|
'CREDENTIALS="%s:%s:%s"' % (username, password, realm)
|
||||||
]
|
]
|
||||||
@ -1158,6 +1191,27 @@ def seProto():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seRTSPPort():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'Streaming RTSP Port',
|
||||||
|
'description': 'sets the TCP port on which the webcam streaming server listens',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 0,
|
||||||
|
'max': 65535,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@additional_config
|
@additional_config
|
||||||
def sePort():
|
def sePort():
|
||||||
if not _get_streameye_enabled():
|
if not _get_streameye_enabled():
|
||||||
@ -1172,7 +1226,6 @@ def sePort():
|
|||||||
'section': 'streaming',
|
'section': 'streaming',
|
||||||
'camera': True,
|
'camera': True,
|
||||||
'required': True,
|
'required': True,
|
||||||
'depends': ['seProto==mjpeg'],
|
|
||||||
'get': _get_streameye_settings,
|
'get': _get_streameye_settings,
|
||||||
'set': _set_streameye_settings,
|
'set': _set_streameye_settings,
|
||||||
'get_set_dict': True
|
'get_set_dict': True
|
||||||
@ -1180,16 +1233,60 @@ def sePort():
|
|||||||
|
|
||||||
|
|
||||||
@additional_config
|
@additional_config
|
||||||
def seRTSPPort():
|
def seMJPEGRes():
|
||||||
if not _get_streameye_enabled():
|
if not _get_streameye_enabled():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'label': 'Streaming Port',
|
'label': 'MJPEG Resolution',
|
||||||
'description': 'sets the TCP port on which the webcam streaming server listens',
|
'description': 'the MJPEG resolution fed to the frontend and used for motion detection on remote machines when streaming RTSP',
|
||||||
|
'type': 'choices',
|
||||||
|
'choices': RESOLUTION_CHOICES,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seMJPEGFramerate():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'MJPEG Frame Rate',
|
||||||
|
'description': 'the MJPEG Frame Rate fed to the frontend and used for motion detection on remote machines when streaming RTSP; for motion detection, 5 works good',
|
||||||
|
'type': 'range',
|
||||||
|
'min': 2,
|
||||||
|
'max': 30,
|
||||||
|
'snap': 0,
|
||||||
|
'ticks': "2|5|10|15|20|25|30",
|
||||||
|
'decimals': 0,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seMJPEGBitrate():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'MJPEG Bitrate',
|
||||||
|
'description': 'the MJPEG Bitrate fed to the frontend and used for motion detection on remote machines when streaming RTSP; for motion detection, 800000 works good',
|
||||||
'type': 'number',
|
'type': 'number',
|
||||||
'min': 0,
|
'min': 0,
|
||||||
'max': 65535,
|
'max': 25000000,
|
||||||
'section': 'streaming',
|
'section': 'streaming',
|
||||||
'camera': True,
|
'camera': True,
|
||||||
'required': True,
|
'required': True,
|
||||||
@ -1218,4 +1315,3 @@ def seAuthMode():
|
|||||||
'set': _set_streameye_settings,
|
'set': _set_streameye_settings,
|
||||||
'get_set_dict': True
|
'get_set_dict': True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
RASPIMJPEG_CONF=/data/etc/raspimjpeg.conf
|
RASPIMJPEG_CONF=/data/etc/raspimjpeg.conf
|
||||||
RASPIMJPEG_LOG=/var/log/raspimjpeg.log
|
RASPIMJPEG_LOG=/var/log/raspimjpeg.log
|
||||||
GSTREAMER_LOG=/var/log/gstreamer.log
|
RTSPSERVER_LOG=/var/log/rtspserver.log
|
||||||
MOTIONEYE_CONF=/data/etc/motioneye.conf
|
MOTIONEYE_CONF=/data/etc/motioneye.conf
|
||||||
STREAMEYE_CONF=/data/etc/streameye.conf
|
STREAMEYE_CONF=/data/etc/streameye.conf
|
||||||
STREAMEYE_LOG=/var/log/streameye.log
|
STREAMEYE_LOG=/var/log/streameye.log
|
||||||
@ -17,122 +17,22 @@ function watch() {
|
|||||||
while true; do
|
while true; do
|
||||||
sleep 5
|
sleep 5
|
||||||
if [ "${PROTO}" = "rtsp" ]; then
|
if [ "${PROTO}" = "rtsp" ]; then
|
||||||
if ! ps aux | grep test-launch | grep -v grep &>/dev/null; then
|
if ! ps aux | grep v4l2multi_stream_mmal | grep -v grep &>/dev/null; then
|
||||||
|
logger -t streameye -s "not running, respawning"
|
||||||
|
start
|
||||||
|
elif ! ps aux | grep v4l2rtspserver | grep -v grep &>/dev/null; then
|
||||||
logger -t streameye -s "not running, respawning"
|
logger -t streameye -s "not running, respawning"
|
||||||
start
|
start
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if ! ps aux | grep raspimjpeg.py | grep -v grep &>/dev/null; then
|
if ! ps aux | grep raspimjpeg.py | grep -v grep &>/dev/null; then
|
||||||
logger -t streameye -s "not running, respawning"
|
logger -t streameye -s "raspimjpeg.py not running, respawning"
|
||||||
start
|
start
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function configure_v4l2_cam() {
|
|
||||||
video_arg="-d $1"
|
|
||||||
|
|
||||||
horizontal_flip="0"
|
|
||||||
hflip=$(grep -e ^hflip ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${hflip}" = "true" ]; then horizontal_flip="1"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=horizontal_flip=${horizontal_flip} &>/dev/null
|
|
||||||
|
|
||||||
vertical_flip="0"
|
|
||||||
vflip=$(grep -e ^vflip ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${vflip}" = "true" ]; then vertical_flip="1"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=vertical_flip=${vertical_flip} &>/dev/null
|
|
||||||
|
|
||||||
rotate=$(grep -e ^rotation ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${rotate}" ]; then rotate="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=rotate=${rotate} &>/dev/null
|
|
||||||
|
|
||||||
brightness=$(grep -e ^brightness ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${brightness}" ]; then brightness="50"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=brightness=${brightness} &>/dev/null
|
|
||||||
|
|
||||||
contrast=$(grep -e ^contrast ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${contrast}" ]; then contrast="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=contrast=${contrast} &>/dev/null
|
|
||||||
|
|
||||||
saturation=$(grep -e ^saturation ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${saturation}" ]; then saturation="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=saturation=${saturation} &>/dev/null
|
|
||||||
|
|
||||||
sharpness=$(grep -e ^sharpness ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${sharpness}" ]; then sharpness="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=sharpness=${sharpness} &>/dev/null
|
|
||||||
|
|
||||||
vstab=$(grep -e ^vstab ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${vstab}" ]; then vstab="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=image_stabilization=${vstab} &>/dev/null
|
|
||||||
|
|
||||||
shutter=$(grep -e ^shutter ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${shutter}" ]; then shutter="0"; fi
|
|
||||||
if [ "${#shutter}" -gt 2 ]; then shutter=$(echo ${shutter/%??/}); else shutter="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=exposure_time_absolute=${shutter} &>/dev/null
|
|
||||||
|
|
||||||
iso=$(grep -e ^iso ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${iso}" ]; then iso="0"; fi
|
|
||||||
if [ "${iso}" -ge 800 ]; then iso="4"
|
|
||||||
elif [ "${iso}" -ge 400 ]; then iso="3"
|
|
||||||
elif [ "${iso}" -ge 200 ]; then iso="2"
|
|
||||||
elif [ "${iso}" -ge 100 ]; then iso="1"
|
|
||||||
else iso="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=iso_sensitivity=${iso} &>/dev/null
|
|
||||||
|
|
||||||
awb=$(grep -e ^awb ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${awb}" = "off" ]; then awb="0"
|
|
||||||
elif [ "${awb}" = "auto" ]; then awb="1"
|
|
||||||
elif [ "${awb}" = "sunlight" ]; then awb="6"
|
|
||||||
elif [ "${awb}" = "cloudy" ]; then awb="8"
|
|
||||||
elif [ "${awb}" = "shade" ]; then awb="9"
|
|
||||||
elif [ "${awb}" = "tungsten" ]; then awb="4"
|
|
||||||
elif [ "${awb}" = "fluorescent" ]; then awb="3"
|
|
||||||
elif [ "${awb}" = "incandescent" ]; then awb="2"
|
|
||||||
elif [ "${awb}" = "flash" ]; then awb="7"
|
|
||||||
elif [ "${awb}" = "horizon" ]; then awb="5"
|
|
||||||
else awb="1"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=white_balance_auto_preset=${awb} &>/dev/null
|
|
||||||
|
|
||||||
metering=$(grep -e ^metering ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${metering}" = "spot" ]; then metering="2"
|
|
||||||
elif [ "${metering}" = "center" ]; then metering="1"
|
|
||||||
else metering="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=exposure_metering_mode=${awb} &>/dev/null
|
|
||||||
|
|
||||||
scene="0"
|
|
||||||
exposure=$(grep -e ^exposure ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${exposure}" = "off" ]; then
|
|
||||||
exposure="1"
|
|
||||||
else
|
|
||||||
if [ "${exposure}" = "night" ]; then scene="8"
|
|
||||||
elif [ "${exposure}" = "backlight" ]; then scene="1"
|
|
||||||
elif [ "${exposure}" = "sports" ]; then scene="11"
|
|
||||||
elif [ "${exposure}" = "snow" ]; then scene="2"
|
|
||||||
elif [ "${exposure}" = "beach" ]; then scene="2"
|
|
||||||
elif [ "${exposure}" = "fireworks" ]; then scene="6"
|
|
||||||
fi
|
|
||||||
exposure="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=auto_exposure=${exposure} &>/dev/null
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=scene_mode=${scene} &>/dev/null
|
|
||||||
|
|
||||||
ev=$(grep -e ^ev ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${ev}" ]; then ev="0"; fi
|
|
||||||
ev=$(expr ${ev} + 25)
|
|
||||||
ev=$(expr ${ev} / 2)
|
|
||||||
if [ "${ev}" -gt 24 ]; then ev="24"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=auto_exposure_bias=${ev} &>/dev/null
|
|
||||||
|
|
||||||
video_bitrate=$(grep -e ^bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${video_bitrate}" ]; then video_bitrate="1000000"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=video_bitrate=${video_bitrate} &>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
function invalid_opt() {
|
function invalid_opt() {
|
||||||
local e match="$1"
|
local e match="$1"
|
||||||
shift
|
shift
|
||||||
@ -143,70 +43,106 @@ function invalid_opt() {
|
|||||||
function start() {
|
function start() {
|
||||||
source ${STREAMEYE_CONF}
|
source ${STREAMEYE_CONF}
|
||||||
streameye_opts="-p ${PORT}"
|
streameye_opts="-p ${PORT}"
|
||||||
|
rtspserver_opts=""
|
||||||
if [ -n "${CREDENTIALS}" ] && [ "${AUTH}" = "basic" ]; then
|
if [ -n "${CREDENTIALS}" ] && [ "${AUTH}" = "basic" ]; then
|
||||||
streameye_opts="${streameye_opts} -a basic -c ${CREDENTIALS}"
|
streameye_opts="${streameye_opts} -a basic -c ${CREDENTIALS}"
|
||||||
|
# TODO: Add RTSP Auth
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${PROTO}" = "rtsp" ]; then
|
if [ "${PROTO}" = "rtsp" ]; then
|
||||||
pid=$(ps | grep test-launch | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
v4l2rtspserver_pid=$(ps | grep v4l2rtspserver | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
if [ -n "${pid}" ]; then
|
v4l2multi_stream_mmal_pid=$(ps | grep v4l2multi_stream_mmal | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
return
|
if [ -n "${v4l2rtspserver_pid}" ]; then
|
||||||
|
if [ -n "${v4l2multi_stream_mmal_pid}" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RTSP_PORT=${RTSP_PORT:-554}
|
RTSP_PORT=${RTSP_PORT:-554}
|
||||||
|
MJPEG_WIDTH=${MJPEG_WIDTH:-640}
|
||||||
|
MJPEG_HEIGHT=${MJPEG_HEIGHT:-480}
|
||||||
|
MJPEG_FRAMERATE=${MJPEG_FRAMERATE:-5}
|
||||||
|
MJPEG_BITRATE=${MJPEG_BITRATE:-800000}
|
||||||
|
|
||||||
iptables -A INPUT -p tcp -s localhost --dport ${RTSP_PORT} -j ACCEPT
|
audio_path=""
|
||||||
iptables -A INPUT -p tcp --dport ${RTSP_PORT} -j DROP
|
|
||||||
|
|
||||||
audio_opts=""
|
audio_opts=""
|
||||||
if [ -n "${AUDIO_DEV}" ]; then
|
if [ -n "${AUDIO_DEV}" ]; then
|
||||||
|
audio_path=",${AUDIO_DEV}"
|
||||||
|
|
||||||
|
# Audio bitrate: default 44100
|
||||||
audio_bitrate=$(grep -e ^audio_bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
audio_bitrate=$(grep -e ^audio_bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
|
# Audio channels: default 2
|
||||||
audio_channels=$(grep -e ^audio_channels ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
audio_channels=$(grep -e ^audio_channels ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
audio_extras=""
|
# Valid audio formats: S16_BE, S16_LE, S24_BE, S24_LE, S32_BE, S32_LE, ALAW, MULAW, S8, MPEG
|
||||||
|
audio_format=$(grep -e ^audio_format ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
if [ -n "${audio_bitrate}" ]; then
|
if [ -n "${audio_bitrate}" ]; then
|
||||||
audio_extras="${audio_extras},rate=${audio_bitrate}"
|
audio_opts="${audio_opts} -A ${audio_bitrate}"
|
||||||
fi
|
fi
|
||||||
if [ -n "${audio_channels}" ]; then
|
if [ -n "${audio_channels}" ]; then
|
||||||
audio_extras="${audio_extras},channels=${audio_channels}"
|
audio_opts="${audio_opts} -C ${audio_channels}"
|
||||||
|
fi
|
||||||
|
if [ -n "${audio_format}" ]; then
|
||||||
|
audio_opts="${audio_opts} -a ${audio_format}"
|
||||||
fi
|
fi
|
||||||
audio_opts="alsasrc device=${AUDIO_DEV} ! audioresample ! audio/x-raw${audio_extras} ! queue ! voaacenc ! rtpmp4gpay pt=97 name=pay1"
|
|
||||||
fi
|
fi
|
||||||
video_path="/dev/video0"
|
# hardcode to 90 for now
|
||||||
if [ -n "${VIDEO_DEV}" ]; then
|
vidid=90
|
||||||
video_path=${VIDEO_DEV}
|
video_path="/dev/video${vidid}"
|
||||||
|
if lsmod | grep v4l2loopback &> /dev/null ; then
|
||||||
|
rmmod v4l2loopback
|
||||||
fi
|
fi
|
||||||
|
modprobe v4l2loopback video_nr=${vidid}
|
||||||
if [ -e "${video_path}" ]; then
|
if [ -e "${video_path}" ]; then
|
||||||
# Only configure camera if it is a Pi Cam
|
valid_opts=("analoggain" "awb" "awbgains" "bitrate" "brightness" "colfx" "contrast" "denoise" "digitalgain" "drc" "ev" "exposure" "flicker" "framerate" "height" "hflip" "imxfx" "intra" "irefresh" "level" "metering" "profile" "roi" "rotation" "saturation" "sharpness" "shutter" "vflip" "vstab" "width" "mjpegbitrate" "mjpegframerate" "mjpegwidth" "mjpegheight")
|
||||||
if v4l2-ctl -d ${video_path} -D | grep -q 'bm2835 mmal'; then
|
raspimjpeg_opts="--videoout ${video_path}"
|
||||||
configure_v4l2_cam ${video_path}
|
while read line; do
|
||||||
|
key=$(echo ${line} | cut -d ' ' -f 1)
|
||||||
|
if invalid_opt "${key}" "${valid_opts[@]}"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if echo "${line}" | grep false &>/dev/null; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if echo "${line}" | grep true &>/dev/null; then
|
||||||
|
line=${key}
|
||||||
|
fi
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --${line}"
|
||||||
|
done < ${RASPIMJPEG_CONF}
|
||||||
|
|
||||||
|
video_iso=$(grep -e ^iso ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
|
if [ -n "${video_iso}" ]; then
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --ISO ${video_iso}"
|
||||||
fi
|
fi
|
||||||
width=$(grep -e ^width ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
height=$(grep -e ^height ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
framerate=$(grep -e ^framerate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
video_extras=""
|
|
||||||
if [ -n "${width}" ]; then
|
|
||||||
video_extras="${video_extras},width=${width}"
|
|
||||||
fi
|
|
||||||
if [ -n "${height}" ]; then
|
|
||||||
video_extras="${video_extras},height=${height}"
|
|
||||||
fi
|
|
||||||
if [ -n "${framerate}" ]; then
|
|
||||||
video_extras="${video_extras},framerate=${framerate}/1"
|
|
||||||
fi
|
|
||||||
video_opts="v4l2src device=${video_path} ! video/x-h264${video_extras} ! h264parse ! rtph264pay name=pay0 pt=96"
|
|
||||||
|
|
||||||
if [ -r ${MOTIONEYE_CONF} ] && grep 'log-level debug' ${MOTIONEYE_CONF} >/dev/null; then
|
if [ -r ${MOTIONEYE_CONF} ] && grep 'log-level debug' ${MOTIONEYE_CONF} >/dev/null; then
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} -v"
|
||||||
streameye_opts="${streameye_opts} -d"
|
streameye_opts="${streameye_opts} -d"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test-launch -p ${RTSP_PORT} -m h264 "\"( ${video_opts} ${audio_opts} )\"" &>${GSTREAMER_LOG} &
|
rtspserver_opts="${rtspserver_opts} -P ${RTSP_PORT} -u h264"
|
||||||
sleep 10
|
video_framerate=$(grep -e ^framerate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
gst-launch-1.0 -v rtspsrc location=rtsp://127.0.0.1:${RTSP_PORT}/h264 latency=0 drop-on-latency=1 ! rtph264depay ! h264parse ! omxh264dec ! videorate ! video/x-raw,framerate=5/1 ! jpegenc ! filesink location=/dev/stdout | streameye ${streameye_opts} &>${STREAMEYE_LOG} &
|
video_intra=$(grep -e ^intra ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
sleep 5
|
if [ -n "${video_framerate}" ]; then
|
||||||
fi
|
rtspserver_opts="${rtspserver_opts} -F ${video_framerate}"
|
||||||
|
if [ -z "${video_intra}" ]; then
|
||||||
|
let "video_intra=$((video_framerate))*2"
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --intra ${video_intra}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
iptables -D INPUT -p tcp --dport ${RTSP_PORT} -j DROP
|
mjpeg_opts="--mjpegbitrate ${MJPEG_BITRATE} --mjpegwidth ${MJPEG_WIDTH} --mjpegheight ${MJPEG_HEIGHT} --mjpegframerate ${MJPEG_FRAMERATE}"
|
||||||
iptables -D INPUT -p tcp -s localhost --dport ${RTSP_PORT} -j ACCEPT
|
raspimjpeg_opts="${raspimjpeg_opts} ${mjpeg_opts}"
|
||||||
|
|
||||||
|
if [ -z "${v4l2multi_stream_mmal_pid}" ]; then
|
||||||
|
v4l2multi_stream_mmal -v ${raspimjpeg_opts} -o - 2>${RTSPSERVER_LOG} | streameye ${streameye_opts} &>${STREAMEYE_LOG} &
|
||||||
|
sleep 10
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${v4l2rtspserver_pid}" ]; then
|
||||||
|
v4l2rtspserver ${rtspserver_opts} ${audio_opts} ${video_path}${audio_path} &>${RTSPSERVER_LOG} &
|
||||||
|
sleep 5
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
@ -244,41 +180,25 @@ function stop() {
|
|||||||
# stop the streameye background watch process
|
# stop the streameye background watch process
|
||||||
ps | grep streameye.sh | grep -v $$ | grep -v S94streameye| grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
ps | grep streameye.sh | grep -v $$ | grep -v S94streameye| grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
||||||
|
|
||||||
# stop the raspimjpeg process
|
# stop the running streaming process
|
||||||
raspimjpeg_pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
processes=( "raspimjpeg.py" "v4l2rtspserver" "v4l2multi_stream_mmal" )
|
||||||
# stop the gst-launch-1.0 process
|
for i in "${processes[@]}"
|
||||||
gst_launch_pid=$(ps | grep gst-launch-1.0 | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
do
|
||||||
# stop the test-launch process
|
pid=$(ps | grep $i | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
test_launch_pid=$(ps | grep test-launch | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
if [ -n "${pid}" ]; then
|
||||||
|
kill -HUP "${pid}" &>/dev/null
|
||||||
|
count=0
|
||||||
|
while kill -0 "${pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
||||||
|
sleep 1
|
||||||
|
count=$((${count} + 1))
|
||||||
|
done
|
||||||
|
kill -KILL "${pid}" &>/dev/null || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
if [ -n "${raspimjpeg_pid}" ]; then
|
# stop the loopback device
|
||||||
kill -HUP "${raspimjpeg_pid}" &>/dev/null
|
if lsmod | grep v4l2loopback &> /dev/null ; then
|
||||||
count=0
|
rmmod v4l2loopback
|
||||||
while kill -0 "${raspimjpeg_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${raspimjpeg_pid}" &>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${gst_launch_pid}" ]; then
|
|
||||||
kill -HUP "${gst_launch_pid}" &>/dev/null
|
|
||||||
count=0
|
|
||||||
while kill -0 "${gst_launch_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${gst_launch_pid}" &>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${test_launch_pid}" ]; then
|
|
||||||
kill -HUP "${test_launch_pid}" &>/dev/null
|
|
||||||
count=0
|
|
||||||
while kill -0 "${test_launch_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${test_launch_pid}" &>/dev/null || true
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,4 +222,3 @@ case "$1" in
|
|||||||
echo $"Usage: $0 {start|stop|restart}"
|
echo $"Usage: $0 {start|stop|restart}"
|
||||||
exit 1
|
exit 1
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
114
board/raspberrypi4/motioneye-modules/streameyectl.py
Normal file → Executable file
114
board/raspberrypi4/motioneye-modules/streameyectl.py
Normal file → Executable file
@ -412,9 +412,13 @@ def _get_streameye_settings(camera_id):
|
|||||||
'seProto': 'mjpeg',
|
'seProto': 'mjpeg',
|
||||||
'seAuthMode': 'disabled',
|
'seAuthMode': 'disabled',
|
||||||
'sePort': 8081,
|
'sePort': 8081,
|
||||||
'seRTSPPort': 554
|
'seRTSPPort': 554,
|
||||||
|
'seMJPEGWidth': 640,
|
||||||
|
'seMJPEGHeight': 480,
|
||||||
|
'seMJPEGFramerate': 5,
|
||||||
|
'seMJPEGBitrate': 800000
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.path.exists(STREAMEYE_CONF):
|
if os.path.exists(STREAMEYE_CONF):
|
||||||
logging.debug('reading streameye settings from %s' % STREAMEYE_CONF)
|
logging.debug('reading streameye settings from %s' % STREAMEYE_CONF)
|
||||||
|
|
||||||
@ -442,15 +446,40 @@ def _get_streameye_settings(camera_id):
|
|||||||
if m:
|
if m:
|
||||||
s['seProto'] = m[0]
|
s['seProto'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_WIDTH="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGWidth'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_HEIGHT="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGHeight'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_FRAMERATE="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGFramerate'] = m[0]
|
||||||
|
|
||||||
|
m = re.findall('^MJPEG_BITRATE="?(\w+)"?', line)
|
||||||
|
if m:
|
||||||
|
s['seMJPEGBitrate'] = m[0]
|
||||||
|
|
||||||
|
s['seMJPEGRes'] = '%sx%s' % (s.pop('seMJPEGWidth'), s.pop('seMJPEGHeight'))
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def _set_streameye_settings(camera_id, s):
|
def _set_streameye_settings(camera_id, s):
|
||||||
s = dict(s)
|
s = dict(s)
|
||||||
|
s['seMJPEGWidth'] = int(s['seMJPEGRes'].split('x')[0])
|
||||||
|
s['seMJPEGHeight'] = int(s.pop('seMJPEGRes').split('x')[1])
|
||||||
|
|
||||||
s.setdefault('sePort', 8081)
|
s.setdefault('sePort', 8081)
|
||||||
s.setdefault('seRTSPPort', 554)
|
s.setdefault('seRTSPPort', 554)
|
||||||
s.setdefault('seAuthMode', 'disabled')
|
s.setdefault('seAuthMode', 'disabled')
|
||||||
|
s.setdefault('seMJPEGWidth', 640)
|
||||||
|
s.setdefault('seMJPEGHeight', 480)
|
||||||
|
s.setdefault('seMJPEGFramerate', 5)
|
||||||
|
s.setdefault('seMJPEGBitrate', 800000)
|
||||||
|
|
||||||
main_config = config.get_main()
|
main_config = config.get_main()
|
||||||
username = main_config['@normal_username']
|
username = main_config['@normal_username']
|
||||||
password = main_config['@normal_password']
|
password = main_config['@normal_password']
|
||||||
@ -462,6 +491,10 @@ def _set_streameye_settings(camera_id, s):
|
|||||||
'PROTO="%s"' % s['seProto'],
|
'PROTO="%s"' % s['seProto'],
|
||||||
'PORT="%s"' % s['sePort'],
|
'PORT="%s"' % s['sePort'],
|
||||||
'RTSP_PORT="%s"' % s['seRTSPPort'],
|
'RTSP_PORT="%s"' % s['seRTSPPort'],
|
||||||
|
'MJPEG_WIDTH="%s"' % s['seMJPEGWidth'],
|
||||||
|
'MJPEG_HEIGHT="%s"' % s['seMJPEGHeight'],
|
||||||
|
'MJPEG_FRAMERATE="%s"' % s['seMJPEGFramerate'],
|
||||||
|
'MJPEG_BITRATE="%s"' % s['seMJPEGBitrate'],
|
||||||
'AUTH="%s"' % s['seAuthMode'],
|
'AUTH="%s"' % s['seAuthMode'],
|
||||||
'CREDENTIALS="%s:%s:%s"' % (username, password, realm)
|
'CREDENTIALS="%s:%s:%s"' % (username, password, realm)
|
||||||
]
|
]
|
||||||
@ -1158,6 +1191,27 @@ def seProto():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seRTSPPort():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'Streaming RTSP Port',
|
||||||
|
'description': 'sets the TCP port on which the webcam streaming server listens',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 0,
|
||||||
|
'max': 65535,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@additional_config
|
@additional_config
|
||||||
def sePort():
|
def sePort():
|
||||||
if not _get_streameye_enabled():
|
if not _get_streameye_enabled():
|
||||||
@ -1172,7 +1226,6 @@ def sePort():
|
|||||||
'section': 'streaming',
|
'section': 'streaming',
|
||||||
'camera': True,
|
'camera': True,
|
||||||
'required': True,
|
'required': True,
|
||||||
'depends': ['seProto==mjpeg'],
|
|
||||||
'get': _get_streameye_settings,
|
'get': _get_streameye_settings,
|
||||||
'set': _set_streameye_settings,
|
'set': _set_streameye_settings,
|
||||||
'get_set_dict': True
|
'get_set_dict': True
|
||||||
@ -1180,16 +1233,60 @@ def sePort():
|
|||||||
|
|
||||||
|
|
||||||
@additional_config
|
@additional_config
|
||||||
def seRTSPPort():
|
def seMJPEGRes():
|
||||||
if not _get_streameye_enabled():
|
if not _get_streameye_enabled():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'label': 'Streaming Port',
|
'label': 'MJPEG Resolution',
|
||||||
'description': 'sets the TCP port on which the webcam streaming server listens',
|
'description': 'the MJPEG resolution fed to the frontend and used for motion detection on remote machines when streaming RTSP',
|
||||||
|
'type': 'choices',
|
||||||
|
'choices': RESOLUTION_CHOICES,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seMJPEGFramerate():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'MJPEG Frame Rate',
|
||||||
|
'description': 'the MJPEG Frame Rate fed to the frontend and used for motion detection on remote machines when streaming RTSP; for motion detection, 5 works good',
|
||||||
|
'type': 'range',
|
||||||
|
'min': 2,
|
||||||
|
'max': 30,
|
||||||
|
'snap': 0,
|
||||||
|
'ticks': "2|5|10|15|20|25|30",
|
||||||
|
'decimals': 0,
|
||||||
|
'section': 'streaming',
|
||||||
|
'camera': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['seProto==rtsp'],
|
||||||
|
'get': _get_streameye_settings,
|
||||||
|
'set': _set_streameye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def seMJPEGBitrate():
|
||||||
|
if not _get_streameye_enabled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'label': 'MJPEG Bitrate',
|
||||||
|
'description': 'the MJPEG Bitrate fed to the frontend and used for motion detection on remote machines when streaming RTSP; for motion detection, 800000 works good',
|
||||||
'type': 'number',
|
'type': 'number',
|
||||||
'min': 0,
|
'min': 0,
|
||||||
'max': 65535,
|
'max': 25000000,
|
||||||
'section': 'streaming',
|
'section': 'streaming',
|
||||||
'camera': True,
|
'camera': True,
|
||||||
'required': True,
|
'required': True,
|
||||||
@ -1218,4 +1315,3 @@ def seAuthMode():
|
|||||||
'set': _set_streameye_settings,
|
'set': _set_streameye_settings,
|
||||||
'get_set_dict': True
|
'get_set_dict': True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
RASPIMJPEG_CONF=/data/etc/raspimjpeg.conf
|
RASPIMJPEG_CONF=/data/etc/raspimjpeg.conf
|
||||||
RASPIMJPEG_LOG=/var/log/raspimjpeg.log
|
RASPIMJPEG_LOG=/var/log/raspimjpeg.log
|
||||||
GSTREAMER_LOG=/var/log/gstreamer.log
|
RTSPSERVER_LOG=/var/log/rtspserver.log
|
||||||
MOTIONEYE_CONF=/data/etc/motioneye.conf
|
MOTIONEYE_CONF=/data/etc/motioneye.conf
|
||||||
STREAMEYE_CONF=/data/etc/streameye.conf
|
STREAMEYE_CONF=/data/etc/streameye.conf
|
||||||
STREAMEYE_LOG=/var/log/streameye.log
|
STREAMEYE_LOG=/var/log/streameye.log
|
||||||
@ -17,122 +17,22 @@ function watch() {
|
|||||||
while true; do
|
while true; do
|
||||||
sleep 5
|
sleep 5
|
||||||
if [ "${PROTO}" = "rtsp" ]; then
|
if [ "${PROTO}" = "rtsp" ]; then
|
||||||
if ! ps aux | grep test-launch | grep -v grep &>/dev/null; then
|
if ! ps aux | grep v4l2multi_stream_mmal | grep -v grep &>/dev/null; then
|
||||||
|
logger -t streameye -s "not running, respawning"
|
||||||
|
start
|
||||||
|
elif ! ps aux | grep v4l2rtspserver | grep -v grep &>/dev/null; then
|
||||||
logger -t streameye -s "not running, respawning"
|
logger -t streameye -s "not running, respawning"
|
||||||
start
|
start
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if ! ps aux | grep raspimjpeg.py | grep -v grep &>/dev/null; then
|
if ! ps aux | grep raspimjpeg.py | grep -v grep &>/dev/null; then
|
||||||
logger -t streameye -s "not running, respawning"
|
logger -t streameye -s "raspimjpeg.py not running, respawning"
|
||||||
start
|
start
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function configure_v4l2_cam() {
|
|
||||||
video_arg="-d $1"
|
|
||||||
|
|
||||||
horizontal_flip="0"
|
|
||||||
hflip=$(grep -e ^hflip ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${hflip}" = "true" ]; then horizontal_flip="1"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=horizontal_flip=${horizontal_flip} &>/dev/null
|
|
||||||
|
|
||||||
vertical_flip="0"
|
|
||||||
vflip=$(grep -e ^vflip ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${vflip}" = "true" ]; then vertical_flip="1"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=vertical_flip=${vertical_flip} &>/dev/null
|
|
||||||
|
|
||||||
rotate=$(grep -e ^rotation ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${rotate}" ]; then rotate="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=rotate=${rotate} &>/dev/null
|
|
||||||
|
|
||||||
brightness=$(grep -e ^brightness ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${brightness}" ]; then brightness="50"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=brightness=${brightness} &>/dev/null
|
|
||||||
|
|
||||||
contrast=$(grep -e ^contrast ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${contrast}" ]; then contrast="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=contrast=${contrast} &>/dev/null
|
|
||||||
|
|
||||||
saturation=$(grep -e ^saturation ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${saturation}" ]; then saturation="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=saturation=${saturation} &>/dev/null
|
|
||||||
|
|
||||||
sharpness=$(grep -e ^sharpness ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${sharpness}" ]; then sharpness="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=sharpness=${sharpness} &>/dev/null
|
|
||||||
|
|
||||||
vstab=$(grep -e ^vstab ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${vstab}" ]; then vstab="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=image_stabilization=${vstab} &>/dev/null
|
|
||||||
|
|
||||||
shutter=$(grep -e ^shutter ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${shutter}" ]; then shutter="0"; fi
|
|
||||||
if [ "${#shutter}" -gt 2 ]; then shutter=$(echo ${shutter/%??/}); else shutter="0"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=exposure_time_absolute=${shutter} &>/dev/null
|
|
||||||
|
|
||||||
iso=$(grep -e ^iso ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${iso}" ]; then iso="0"; fi
|
|
||||||
if [ "${iso}" -ge 800 ]; then iso="4"
|
|
||||||
elif [ "${iso}" -ge 400 ]; then iso="3"
|
|
||||||
elif [ "${iso}" -ge 200 ]; then iso="2"
|
|
||||||
elif [ "${iso}" -ge 100 ]; then iso="1"
|
|
||||||
else iso="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=iso_sensitivity=${iso} &>/dev/null
|
|
||||||
|
|
||||||
awb=$(grep -e ^awb ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${awb}" = "off" ]; then awb="0"
|
|
||||||
elif [ "${awb}" = "auto" ]; then awb="1"
|
|
||||||
elif [ "${awb}" = "sunlight" ]; then awb="6"
|
|
||||||
elif [ "${awb}" = "cloudy" ]; then awb="8"
|
|
||||||
elif [ "${awb}" = "shade" ]; then awb="9"
|
|
||||||
elif [ "${awb}" = "tungsten" ]; then awb="4"
|
|
||||||
elif [ "${awb}" = "fluorescent" ]; then awb="3"
|
|
||||||
elif [ "${awb}" = "incandescent" ]; then awb="2"
|
|
||||||
elif [ "${awb}" = "flash" ]; then awb="7"
|
|
||||||
elif [ "${awb}" = "horizon" ]; then awb="5"
|
|
||||||
else awb="1"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=white_balance_auto_preset=${awb} &>/dev/null
|
|
||||||
|
|
||||||
metering=$(grep -e ^metering ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${metering}" = "spot" ]; then metering="2"
|
|
||||||
elif [ "${metering}" = "center" ]; then metering="1"
|
|
||||||
else metering="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=exposure_metering_mode=${awb} &>/dev/null
|
|
||||||
|
|
||||||
scene="0"
|
|
||||||
exposure=$(grep -e ^exposure ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ "${exposure}" = "off" ]; then
|
|
||||||
exposure="1"
|
|
||||||
else
|
|
||||||
if [ "${exposure}" = "night" ]; then scene="8"
|
|
||||||
elif [ "${exposure}" = "backlight" ]; then scene="1"
|
|
||||||
elif [ "${exposure}" = "sports" ]; then scene="11"
|
|
||||||
elif [ "${exposure}" = "snow" ]; then scene="2"
|
|
||||||
elif [ "${exposure}" = "beach" ]; then scene="2"
|
|
||||||
elif [ "${exposure}" = "fireworks" ]; then scene="6"
|
|
||||||
fi
|
|
||||||
exposure="0"
|
|
||||||
fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=auto_exposure=${exposure} &>/dev/null
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=scene_mode=${scene} &>/dev/null
|
|
||||||
|
|
||||||
ev=$(grep -e ^ev ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${ev}" ]; then ev="0"; fi
|
|
||||||
ev=$(expr ${ev} + 25)
|
|
||||||
ev=$(expr ${ev} / 2)
|
|
||||||
if [ "${ev}" -gt 24 ]; then ev="24"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=auto_exposure_bias=${ev} &>/dev/null
|
|
||||||
|
|
||||||
video_bitrate=$(grep -e ^bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
if [ -z "${video_bitrate}" ]; then video_bitrate="1000000"; fi
|
|
||||||
v4l2-ctl ${video_arg} --set-ctrl=video_bitrate=${video_bitrate} &>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
function invalid_opt() {
|
function invalid_opt() {
|
||||||
local e match="$1"
|
local e match="$1"
|
||||||
shift
|
shift
|
||||||
@ -143,70 +43,106 @@ function invalid_opt() {
|
|||||||
function start() {
|
function start() {
|
||||||
source ${STREAMEYE_CONF}
|
source ${STREAMEYE_CONF}
|
||||||
streameye_opts="-p ${PORT}"
|
streameye_opts="-p ${PORT}"
|
||||||
|
rtspserver_opts=""
|
||||||
if [ -n "${CREDENTIALS}" ] && [ "${AUTH}" = "basic" ]; then
|
if [ -n "${CREDENTIALS}" ] && [ "${AUTH}" = "basic" ]; then
|
||||||
streameye_opts="${streameye_opts} -a basic -c ${CREDENTIALS}"
|
streameye_opts="${streameye_opts} -a basic -c ${CREDENTIALS}"
|
||||||
|
# TODO: Add RTSP Auth
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${PROTO}" = "rtsp" ]; then
|
if [ "${PROTO}" = "rtsp" ]; then
|
||||||
pid=$(ps | grep test-launch | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
v4l2rtspserver_pid=$(ps | grep v4l2rtspserver | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
if [ -n "${pid}" ]; then
|
v4l2multi_stream_mmal_pid=$(ps | grep v4l2multi_stream_mmal | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
return
|
if [ -n "${v4l2rtspserver_pid}" ]; then
|
||||||
|
if [ -n "${v4l2multi_stream_mmal_pid}" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RTSP_PORT=${RTSP_PORT:-554}
|
RTSP_PORT=${RTSP_PORT:-554}
|
||||||
|
MJPEG_WIDTH=${MJPEG_WIDTH:-640}
|
||||||
|
MJPEG_HEIGHT=${MJPEG_HEIGHT:-480}
|
||||||
|
MJPEG_FRAMERATE=${MJPEG_FRAMERATE:-5}
|
||||||
|
MJPEG_BITRATE=${MJPEG_BITRATE:-800000}
|
||||||
|
|
||||||
iptables -A INPUT -p tcp -s localhost --dport ${RTSP_PORT} -j ACCEPT
|
audio_path=""
|
||||||
iptables -A INPUT -p tcp --dport ${RTSP_PORT} -j DROP
|
|
||||||
|
|
||||||
audio_opts=""
|
audio_opts=""
|
||||||
if [ -n "${AUDIO_DEV}" ]; then
|
if [ -n "${AUDIO_DEV}" ]; then
|
||||||
|
audio_path=",${AUDIO_DEV}"
|
||||||
|
|
||||||
|
# Audio bitrate: default 44100
|
||||||
audio_bitrate=$(grep -e ^audio_bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
audio_bitrate=$(grep -e ^audio_bitrate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
|
# Audio channels: default 2
|
||||||
audio_channels=$(grep -e ^audio_channels ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
audio_channels=$(grep -e ^audio_channels ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
audio_extras=""
|
# Valid audio formats: S16_BE, S16_LE, S24_BE, S24_LE, S32_BE, S32_LE, ALAW, MULAW, S8, MPEG
|
||||||
|
audio_format=$(grep -e ^audio_format ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
if [ -n "${audio_bitrate}" ]; then
|
if [ -n "${audio_bitrate}" ]; then
|
||||||
audio_extras="${audio_extras},rate=${audio_bitrate}"
|
audio_opts="${audio_opts} -A ${audio_bitrate}"
|
||||||
fi
|
fi
|
||||||
if [ -n "${audio_channels}" ]; then
|
if [ -n "${audio_channels}" ]; then
|
||||||
audio_extras="${audio_extras},channels=${audio_channels}"
|
audio_opts="${audio_opts} -C ${audio_channels}"
|
||||||
|
fi
|
||||||
|
if [ -n "${audio_format}" ]; then
|
||||||
|
audio_opts="${audio_opts} -a ${audio_format}"
|
||||||
fi
|
fi
|
||||||
audio_opts="alsasrc device=${AUDIO_DEV} ! audioresample ! audio/x-raw${audio_extras} ! queue ! voaacenc ! rtpmp4gpay pt=97 name=pay1"
|
|
||||||
fi
|
fi
|
||||||
video_path="/dev/video0"
|
# hardcode to 90 for now
|
||||||
if [ -n "${VIDEO_DEV}" ]; then
|
vidid=90
|
||||||
video_path=${VIDEO_DEV}
|
video_path="/dev/video${vidid}"
|
||||||
|
if lsmod | grep v4l2loopback &> /dev/null ; then
|
||||||
|
rmmod v4l2loopback
|
||||||
fi
|
fi
|
||||||
|
modprobe v4l2loopback video_nr=${vidid}
|
||||||
if [ -e "${video_path}" ]; then
|
if [ -e "${video_path}" ]; then
|
||||||
# Only configure camera if it is a Pi Cam
|
valid_opts=("analoggain" "awb" "awbgains" "bitrate" "brightness" "colfx" "contrast" "denoise" "digitalgain" "drc" "ev" "exposure" "flicker" "framerate" "height" "hflip" "imxfx" "intra" "irefresh" "level" "metering" "profile" "roi" "rotation" "saturation" "sharpness" "shutter" "vflip" "vstab" "width" "mjpegbitrate" "mjpegframerate" "mjpegwidth" "mjpegheight")
|
||||||
if v4l2-ctl -d ${video_path} -D | grep -q 'bm2835 mmal'; then
|
raspimjpeg_opts="--videoout ${video_path}"
|
||||||
configure_v4l2_cam ${video_path}
|
while read line; do
|
||||||
|
key=$(echo ${line} | cut -d ' ' -f 1)
|
||||||
|
if invalid_opt "${key}" "${valid_opts[@]}"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if echo "${line}" | grep false &>/dev/null; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if echo "${line}" | grep true &>/dev/null; then
|
||||||
|
line=${key}
|
||||||
|
fi
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --${line}"
|
||||||
|
done < ${RASPIMJPEG_CONF}
|
||||||
|
|
||||||
|
video_iso=$(grep -e ^iso ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
|
if [ -n "${video_iso}" ]; then
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --ISO ${video_iso}"
|
||||||
fi
|
fi
|
||||||
width=$(grep -e ^width ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
height=$(grep -e ^height ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
framerate=$(grep -e ^framerate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
|
||||||
video_extras=""
|
|
||||||
if [ -n "${width}" ]; then
|
|
||||||
video_extras="${video_extras},width=${width}"
|
|
||||||
fi
|
|
||||||
if [ -n "${height}" ]; then
|
|
||||||
video_extras="${video_extras},height=${height}"
|
|
||||||
fi
|
|
||||||
if [ -n "${framerate}" ]; then
|
|
||||||
video_extras="${video_extras},framerate=${framerate}/1"
|
|
||||||
fi
|
|
||||||
video_opts="v4l2src device=${video_path} ! video/x-h264${video_extras} ! h264parse ! rtph264pay name=pay0 pt=96"
|
|
||||||
|
|
||||||
if [ -r ${MOTIONEYE_CONF} ] && grep 'log-level debug' ${MOTIONEYE_CONF} >/dev/null; then
|
if [ -r ${MOTIONEYE_CONF} ] && grep 'log-level debug' ${MOTIONEYE_CONF} >/dev/null; then
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} -v"
|
||||||
streameye_opts="${streameye_opts} -d"
|
streameye_opts="${streameye_opts} -d"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test-launch -p ${RTSP_PORT} -m h264 "\"( ${video_opts} ${audio_opts} )\"" &>${GSTREAMER_LOG} &
|
rtspserver_opts="${rtspserver_opts} -P ${RTSP_PORT} -u h264"
|
||||||
sleep 10
|
video_framerate=$(grep -e ^framerate ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
gst-launch-1.0 -v rtspsrc location=rtsp://127.0.0.1:${RTSP_PORT}/h264 latency=0 drop-on-latency=1 ! rtph264depay ! h264parse ! omxh264dec ! videorate ! video/x-raw,framerate=5/1 ! jpegenc ! filesink location=/dev/stdout | streameye ${streameye_opts} &>${STREAMEYE_LOG} &
|
video_intra=$(grep -e ^intra ${RASPIMJPEG_CONF} | cut -d ' ' -f 2)
|
||||||
sleep 5
|
if [ -n "${video_framerate}" ]; then
|
||||||
fi
|
rtspserver_opts="${rtspserver_opts} -F ${video_framerate}"
|
||||||
|
if [ -z "${video_intra}" ]; then
|
||||||
|
let "video_intra=$((video_framerate))*2"
|
||||||
|
raspimjpeg_opts="${raspimjpeg_opts} --intra ${video_intra}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
iptables -D INPUT -p tcp --dport ${RTSP_PORT} -j DROP
|
mjpeg_opts="--mjpegbitrate ${MJPEG_BITRATE} --mjpegwidth ${MJPEG_WIDTH} --mjpegheight ${MJPEG_HEIGHT} --mjpegframerate ${MJPEG_FRAMERATE}"
|
||||||
iptables -D INPUT -p tcp -s localhost --dport ${RTSP_PORT} -j ACCEPT
|
raspimjpeg_opts="${raspimjpeg_opts} ${mjpeg_opts}"
|
||||||
|
|
||||||
|
if [ -z "${v4l2multi_stream_mmal_pid}" ]; then
|
||||||
|
v4l2multi_stream_mmal -v ${raspimjpeg_opts} -o - 2>${RTSPSERVER_LOG} | streameye ${streameye_opts} &>${STREAMEYE_LOG} &
|
||||||
|
sleep 10
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${v4l2rtspserver_pid}" ]; then
|
||||||
|
v4l2rtspserver ${rtspserver_opts} ${audio_opts} ${video_path}${audio_path} &>${RTSPSERVER_LOG} &
|
||||||
|
sleep 5
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
@ -244,41 +180,25 @@ function stop() {
|
|||||||
# stop the streameye background watch process
|
# stop the streameye background watch process
|
||||||
ps | grep streameye.sh | grep -v $$ | grep -v S94streameye| grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
ps | grep streameye.sh | grep -v $$ | grep -v S94streameye| grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
||||||
|
|
||||||
# stop the raspimjpeg process
|
# stop the running streaming process
|
||||||
raspimjpeg_pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
processes=( "raspimjpeg.py" "v4l2rtspserver" "v4l2multi_stream_mmal" )
|
||||||
# stop the gst-launch-1.0 process
|
for i in "${processes[@]}"
|
||||||
gst_launch_pid=$(ps | grep gst-launch-1.0 | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
do
|
||||||
# stop the test-launch process
|
pid=$(ps | grep $i | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
test_launch_pid=$(ps | grep test-launch | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
if [ -n "${pid}" ]; then
|
||||||
|
kill -HUP "${pid}" &>/dev/null
|
||||||
|
count=0
|
||||||
|
while kill -0 "${pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
||||||
|
sleep 1
|
||||||
|
count=$((${count} + 1))
|
||||||
|
done
|
||||||
|
kill -KILL "${pid}" &>/dev/null || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
if [ -n "${raspimjpeg_pid}" ]; then
|
# stop the loopback device
|
||||||
kill -HUP "${raspimjpeg_pid}" &>/dev/null
|
if lsmod | grep v4l2loopback &> /dev/null ; then
|
||||||
count=0
|
rmmod v4l2loopback
|
||||||
while kill -0 "${raspimjpeg_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${raspimjpeg_pid}" &>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${gst_launch_pid}" ]; then
|
|
||||||
kill -HUP "${gst_launch_pid}" &>/dev/null
|
|
||||||
count=0
|
|
||||||
while kill -0 "${gst_launch_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${gst_launch_pid}" &>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${test_launch_pid}" ]; then
|
|
||||||
kill -HUP "${test_launch_pid}" &>/dev/null
|
|
||||||
count=0
|
|
||||||
while kill -0 "${test_launch_pid}" &>/dev/null && [ ${count} -lt 5 ]; do
|
|
||||||
sleep 1
|
|
||||||
count=$((${count} + 1))
|
|
||||||
done
|
|
||||||
kill -KILL "${test_launch_pid}" &>/dev/null || true
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,4 +222,3 @@ case "$1" in
|
|||||||
echo $"Usage: $0 {start|stop|restart}"
|
echo $"Usage: $0 {start|stop|restart}"
|
||||||
exit 1
|
exit 1
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user