From e7de8e6d7b51a16e1c4ce31e4e7b366fd934466d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Jun 2017 10:59:50 -0400 Subject: [PATCH 001/375] use variable instead of recalculating --- scripts/zmtelemetry.pl.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/zmtelemetry.pl.in b/scripts/zmtelemetry.pl.in index e00f8ec0a..b3b339593 100644 --- a/scripts/zmtelemetry.pl.in +++ b/scripts/zmtelemetry.pl.in @@ -76,7 +76,7 @@ if ( $Config{ZM_TELEMETRY_DATA} or $force ) { Warning( 'Seconds since last check is negative! Which means that lastCheck is in the future!' ); next; } - if ( ( ($now-$lastCheck) > $interval ) or $force ) { + if ( ( ($since_last_check) > $interval ) or $force ) { print "Collecting data to send to ZoneMinder Telemetry server.\n"; my $dbh = zmDbConnect(); # Build the telemetry hash From 52d5099677c13c840218d030b52112f1df6135ff Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Jun 2017 11:01:57 -0400 Subject: [PATCH 002/375] fix quotes --- scripts/zmtelemetry.pl.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/zmtelemetry.pl.in b/scripts/zmtelemetry.pl.in index b3b339593..62dbf67f8 100644 --- a/scripts/zmtelemetry.pl.in +++ b/scripts/zmtelemetry.pl.in @@ -149,7 +149,7 @@ sub sendData { my $server_endpoint = $Config{ZM_TELEMETRY_SERVER_ENDPOINT}; if ( $Config{ZM_UPDATE_CHECK_PROXY} ) { - $ua->proxy( "https", $Config{ZM_UPDATE_CHECK_PROXY} ); + $ua->proxy( 'https', $Config{ZM_UPDATE_CHECK_PROXY} ); } Debug("Posting telemetry data to: $server_endpoint"); @@ -166,7 +166,7 @@ sub sendData { my $resp_msg = $resp->decoded_content; my $resp_code = $resp->code; if ($resp->is_success) { - Info("Telemetry data uploaded successfully."); + Info('Telemetry data uploaded successfully.'); Debug("Telemetry server upload success response message: $resp_msg"); } else { Warning("Telemetry server returned HTTP POST error code: $resp_code"); From e0d99018aaab10b367bde40833afd496b3b9ee25 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 19 Oct 2017 16:08:20 -0400 Subject: [PATCH 003/375] Google code style, add a warning if no sd --- src/zm_stream.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index c0b8701a2..2fd7666bb 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -77,17 +77,13 @@ void StreamBase::updateFrameRate( double fps ) Debug( 3, "aEFPS:%.2f, aFM:%d", effective_fps, frame_mod ); } -bool StreamBase::checkCommandQueue() -{ - if ( sd >= 0 ) - { +bool StreamBase::checkCommandQueue() { + if ( sd >= 0 ) { CmdMsg msg; memset( &msg, 0, sizeof(msg) ); int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 ); - if ( nbytes < 0 ) - { - if ( errno != EAGAIN ) - { + if ( nbytes < 0 ) { + if ( errno != EAGAIN ) { Fatal( "recvfrom(), errno = %d, error = %s", errno, strerror(errno) ); } } @@ -95,11 +91,12 @@ bool StreamBase::checkCommandQueue() //{ //Error( "Partial message received, expected %d bytes, got %d", sizeof(msg), nbytes ); //} - else - { + else { processCommand( &msg ); return( true ); } + } else { + Warning("No sd in checkCommandQueue, comms not open?"); } return( false ); } From b6a1885167c40e67f13f86c4a61216e83c04adcb Mon Sep 17 00:00:00 2001 From: digital-gnome <31593470+digital-gnome@users.noreply.github.com> Date: Sat, 18 Nov 2017 19:02:56 -0500 Subject: [PATCH 004/375] fix generated video download (#2002) Fixes out of memory php error when downloading large generated video files --- web/skins/classic/views/video.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web/skins/classic/views/video.php b/web/skins/classic/views/video.php index cfbb6f929..6a20ed319 100644 --- a/web/skins/classic/views/video.php +++ b/web/skins/classic/views/video.php @@ -101,6 +101,9 @@ if ( isset($_REQUEST['downloadIndex']) ) header( "Content-Transfer-Encoding: binary" ); header( "Content-Type: application/force-download" ); header( "Content-Length: ".filesize($videoFiles[$downloadIndex]) ); + while ( ob_get_level() > 0 ) { + ob_end_clean(); + } readfile( $videoFiles[$downloadIndex] ); exit; } From 6e240f669cf0188019e55e81ece9d4682c7896b2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 8 Feb 2018 14:25:58 -0800 Subject: [PATCH 005/375] fix filtering --- web/skins/classic/views/montagereview.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index 031de0896..0bbb17653 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -122,8 +122,8 @@ if ( ! empty( $user['MonitorIds'] ) ) { $eventsSql .= ' AND M.Id IN ('.$user['MonitorIds'].')'; $frameSql .= ' AND E.MonitorId IN ('.$user['MonitorIds'].')'; } -if ( count($selected_monitor_ids) ) { - $monitor_ids_sql = ' IN (' . implode(',',$selected_monitor_ids).')'; +if ( count($displayMonitors) ) { + $monitor_ids_sql = ' IN (' . implode(',',array_map( function($Monitor){return $Monitor['Id'];}, $displayMonitors) ) . ')'; $eventsSql .= ' AND M.Id '.$monitor_ids_sql; $frameSql .= ' AND E.MonitorId '.$monitor_ids_sql; } From ebc6bf0dcc679340ec9713d08a1777bde377e946 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 21 Feb 2018 09:56:19 -0600 Subject: [PATCH 006/375] move debian tweaks to startpackpack.sh --- .travis.yml | 4 ---- utils/packpack/startpackpack.sh | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index ddcd1e519..92aeeec56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,10 +30,6 @@ install: - update-binfmts --enable qemu-arm env: - global: - - DEB_BUILD_OPTIONS="parallel=4" - - DEBUILD_LINTIAN="no" - - SMPFLAGS="-j4" matrix: - OS=el DIST=6 - OS=el DIST=6 ARCH=i386 DOCKER_REPO=knnniggett/packpack diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh index 9d58a40a9..9cb5f7e21 100755 --- a/utils/packpack/startpackpack.sh +++ b/utils/packpack/startpackpack.sh @@ -231,6 +231,7 @@ execpackpack () { parms="-f utils/packpack/redhat_package.mk redhat_package" else parms="" + export SMPFLAGS="-j$(nproc) --no-lintian" fi if [ "${TRAVIS}" == "true" ]; then From f8000d7438d7afe8848fa43a94821e08f3281715 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 21 Feb 2018 10:16:35 -0600 Subject: [PATCH 007/375] Update startpackpack.sh --- utils/packpack/startpackpack.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh index 9cb5f7e21..a2c7f4314 100755 --- a/utils/packpack/startpackpack.sh +++ b/utils/packpack/startpackpack.sh @@ -231,7 +231,7 @@ execpackpack () { parms="-f utils/packpack/redhat_package.mk redhat_package" else parms="" - export SMPFLAGS="-j$(nproc) --no-lintian" + export SMPFLAGS="-j4 --lintian --no-lintian" fi if [ "${TRAVIS}" == "true" ]; then From 4832de9217165d0a8b474ead53438ddf12f7b9a9 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 21 Feb 2018 10:19:35 -0600 Subject: [PATCH 008/375] fix typo --- utils/packpack/startpackpack.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh index a2c7f4314..7a7dc7d2f 100755 --- a/utils/packpack/startpackpack.sh +++ b/utils/packpack/startpackpack.sh @@ -231,7 +231,7 @@ execpackpack () { parms="-f utils/packpack/redhat_package.mk redhat_package" else parms="" - export SMPFLAGS="-j4 --lintian --no-lintian" + export SMPFLAGS="-j4 --lintian-opts --no-lintian" fi if [ "${TRAVIS}" == "true" ]; then From b6ad2b6ad75a57c4223cdfb29a458c64de7de6af Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 21 Feb 2018 12:15:10 -0600 Subject: [PATCH 009/375] patch packpack to support custom environment vars --- utils/packpack/environment | 3 +++ utils/packpack/envvars.patch | 25 +++++++++++++++++++++++++ utils/packpack/startpackpack.sh | 9 ++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 utils/packpack/environment create mode 100644 utils/packpack/envvars.patch diff --git a/utils/packpack/environment b/utils/packpack/environment new file mode 100644 index 000000000..4c8305d6f --- /dev/null +++ b/utils/packpack/environment @@ -0,0 +1,3 @@ +DEB_BUILD_OPTIONS="parallel=4" +DEBUILD_LINTIAN="no" + diff --git a/utils/packpack/envvars.patch b/utils/packpack/envvars.patch new file mode 100644 index 000000000..b1406a09b --- /dev/null +++ b/utils/packpack/envvars.patch @@ -0,0 +1,25 @@ +From 871835ecc4ee380fe42d1ef2a58dca9dc4e9af5f Mon Sep 17 00:00:00 2001 +From: Andrew Bauer +Date: Wed, 21 Feb 2018 12:07:12 -0600 +Subject: [PATCH] allow one to load custom environment variables + +--- + packpack | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/packpack b/packpack +index 6f4c80f..abab604 100755 +--- a/packpack ++++ b/packpack +@@ -128,6 +128,11 @@ chmod a+x ${BUILDDIR}/userwrapper.sh + env | grep -E "^PRODUCT=|^VERSION=|^RELEASE=|^ABBREV=|^TARBALL_|^CHANGELOG_|^CCACHE_|^PACKAGECLOUD_|^SMPFLAGS=|^OS=|^DIST=" \ + > ${BUILDDIR}/env + ++# Load user environment variables ++if [ -f "${USER_ENV_FILE}" ]; then ++ cat ${USER_ENV_FILE} >> ${BUILDDIR}/env ++fi ++ + # + # Setup cache directory + # diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh index 7a7dc7d2f..49446a9bf 100755 --- a/utils/packpack/startpackpack.sh +++ b/utils/packpack/startpackpack.sh @@ -108,6 +108,12 @@ commonprep () { patch -p1 < utils/packpack/packpack-rpm.patch fi + # Patch packpack + patch --dry-run --silent -f -p1 < utils/packpack/envvars.patch + if [ $? -eq 0 ]; then + patch -p1 < utils/packpack/envvars.patch + fi + # The rpm specfile requires we download the tarball and manually move it into place # Might as well do this for Debian as well, rather than git submodule init CRUDVER="3.0.10" @@ -231,7 +237,8 @@ execpackpack () { parms="-f utils/packpack/redhat_package.mk redhat_package" else parms="" - export SMPFLAGS="-j4 --lintian-opts --no-lintian" + export SMPFLAGS="-j4" + export USER_ENV_FILE="utils/packpack/environment" fi if [ "${TRAVIS}" == "true" ]; then From 8ef0386db2d4f1f60db3774756962f0a9b0d5a6a Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 21 Feb 2018 12:30:33 -0600 Subject: [PATCH 010/375] adjust the path in the packpack patch file --- utils/packpack/envvars.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/packpack/envvars.patch b/utils/packpack/envvars.patch index b1406a09b..3a3f2682a 100644 --- a/utils/packpack/envvars.patch +++ b/utils/packpack/envvars.patch @@ -9,8 +9,8 @@ Subject: [PATCH] allow one to load custom environment variables diff --git a/packpack b/packpack index 6f4c80f..abab604 100755 ---- a/packpack -+++ b/packpack +--- a/packpack/packpack ++++ b/packpack/packpack @@ -128,6 +128,11 @@ chmod a+x ${BUILDDIR}/userwrapper.sh env | grep -E "^PRODUCT=|^VERSION=|^RELEASE=|^ABBREV=|^TARBALL_|^CHANGELOG_|^CCACHE_|^PACKAGECLOUD_|^SMPFLAGS=|^OS=|^DIST=" \ > ${BUILDDIR}/env From 075f8d461c08d9360f5b277971f8057816f77aeb Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 21 Feb 2018 17:15:18 -0600 Subject: [PATCH 011/375] Docker treats quotes literally in env-file see: https://github.com/moby/moby/issues/11443#issuecomment-99198051 --- utils/packpack/environment | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/packpack/environment b/utils/packpack/environment index 4c8305d6f..64ed12781 100644 --- a/utils/packpack/environment +++ b/utils/packpack/environment @@ -1,3 +1,3 @@ -DEB_BUILD_OPTIONS="parallel=4" -DEBUILD_LINTIAN="no" +DEB_BUILD_OPTIONS=parallel=4 +DEBUILD_LINTIAN=no From 7b9cb59df92a7a340ced39ae951ca560a8b56a12 Mon Sep 17 00:00:00 2001 From: Andy Bauer Date: Thu, 22 Feb 2018 08:58:33 -0600 Subject: [PATCH 012/375] force no-lintian flag --- .travis.yml | 2 ++ utils/packpack/environment | 3 --- utils/packpack/envvars.patch | 25 ------------------------- utils/packpack/nolintian.patch | 22 ++++++++++++++++++++++ utils/packpack/startpackpack.sh | 8 +++----- 5 files changed, 27 insertions(+), 33 deletions(-) delete mode 100644 utils/packpack/environment delete mode 100644 utils/packpack/envvars.patch create mode 100644 utils/packpack/nolintian.patch diff --git a/.travis.yml b/.travis.yml index 92aeeec56..531fed4da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,8 @@ install: - update-binfmts --enable qemu-arm env: + global: + - SMPFLAGS=-j4 matrix: - OS=el DIST=6 - OS=el DIST=6 ARCH=i386 DOCKER_REPO=knnniggett/packpack diff --git a/utils/packpack/environment b/utils/packpack/environment deleted file mode 100644 index 64ed12781..000000000 --- a/utils/packpack/environment +++ /dev/null @@ -1,3 +0,0 @@ -DEB_BUILD_OPTIONS=parallel=4 -DEBUILD_LINTIAN=no - diff --git a/utils/packpack/envvars.patch b/utils/packpack/envvars.patch deleted file mode 100644 index 3a3f2682a..000000000 --- a/utils/packpack/envvars.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 871835ecc4ee380fe42d1ef2a58dca9dc4e9af5f Mon Sep 17 00:00:00 2001 -From: Andrew Bauer -Date: Wed, 21 Feb 2018 12:07:12 -0600 -Subject: [PATCH] allow one to load custom environment variables - ---- - packpack | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/packpack b/packpack -index 6f4c80f..abab604 100755 ---- a/packpack/packpack -+++ b/packpack/packpack -@@ -128,6 +128,11 @@ chmod a+x ${BUILDDIR}/userwrapper.sh - env | grep -E "^PRODUCT=|^VERSION=|^RELEASE=|^ABBREV=|^TARBALL_|^CHANGELOG_|^CCACHE_|^PACKAGECLOUD_|^SMPFLAGS=|^OS=|^DIST=" \ - > ${BUILDDIR}/env - -+# Load user environment variables -+if [ -f "${USER_ENV_FILE}" ]; then -+ cat ${USER_ENV_FILE} >> ${BUILDDIR}/env -+fi -+ - # - # Setup cache directory - # diff --git a/utils/packpack/nolintian.patch b/utils/packpack/nolintian.patch new file mode 100644 index 000000000..3ef36451c --- /dev/null +++ b/utils/packpack/nolintian.patch @@ -0,0 +1,22 @@ +From 634281a4204467b9a3c8a1a5febcc8dd9828e0f6 Mon Sep 17 00:00:00 2001 +From: Andy Bauer +Date: Thu, 22 Feb 2018 08:53:50 -0600 +Subject: [PATCH] don't run lintian checks to speed up build + +--- + pack/deb.mk | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pack/deb.mk b/pack/deb.mk +index de4a0b7..bddf9df 100644 +--- a/pack/deb.mk ++++ b/pack/deb.mk +@@ -130,7 +130,7 @@ $(BUILDDIR)/$(DPKG_CHANGES): $(BUILDDIR)/$(PRODUCT)-$(VERSION)/debian \ + @echo "Building Debian packages" + @echo "-------------------------------------------------------------------" + cd $(BUILDDIR)/$(PRODUCT)-$(VERSION) && \ +- debuild --preserve-envvar CCACHE_DIR --prepend-path=/usr/lib/ccache \ ++ debuild --no-lintian --preserve-envvar CCACHE_DIR --prepend-path=/usr/lib/ccache \ + -Z$(TARBALL_COMPRESSOR) -uc -us $(SMPFLAGS) + rm -rf $(BUILDDIR)/$(PRODUCT)-$(VERSION)/ + @echo "------------------------------------------------------------------" diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh index 49446a9bf..146399690 100755 --- a/utils/packpack/startpackpack.sh +++ b/utils/packpack/startpackpack.sh @@ -108,10 +108,10 @@ commonprep () { patch -p1 < utils/packpack/packpack-rpm.patch fi - # Patch packpack - patch --dry-run --silent -f -p1 < utils/packpack/envvars.patch + # Skip deb lintian checks to speed up the build + patch --dry-run --silent -f -p1 < utils/packpack/nolintian.patch if [ $? -eq 0 ]; then - patch -p1 < utils/packpack/envvars.patch + patch -p1 < utils/packpack/nolintian.patch fi # The rpm specfile requires we download the tarball and manually move it into place @@ -237,8 +237,6 @@ execpackpack () { parms="-f utils/packpack/redhat_package.mk redhat_package" else parms="" - export SMPFLAGS="-j4" - export USER_ENV_FILE="utils/packpack/environment" fi if [ "${TRAVIS}" == "true" ]; then From b19cb60540356fa1603abffbc24d0693665cc093 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 22 Feb 2018 09:16:59 -0600 Subject: [PATCH 013/375] update path in patch file (again) --- utils/packpack/nolintian.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/packpack/nolintian.patch b/utils/packpack/nolintian.patch index 3ef36451c..89b93a4c3 100644 --- a/utils/packpack/nolintian.patch +++ b/utils/packpack/nolintian.patch @@ -9,8 +9,8 @@ Subject: [PATCH] don't run lintian checks to speed up build diff --git a/pack/deb.mk b/pack/deb.mk index de4a0b7..bddf9df 100644 ---- a/pack/deb.mk -+++ b/pack/deb.mk +--- a/packpack/pack/deb.mk ++++ b/packpack/pack/deb.mk @@ -130,7 +130,7 @@ $(BUILDDIR)/$(DPKG_CHANGES): $(BUILDDIR)/$(PRODUCT)-$(VERSION)/debian \ @echo "Building Debian packages" @echo "-------------------------------------------------------------------" From ab11e9ec38d562c3227356ac3c35008294ce37b2 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 23 Feb 2018 11:48:35 -0600 Subject: [PATCH 014/375] Update zoneminder.spec --- distros/redhat/zoneminder.spec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 10ce1ff0a..0226d777f 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -83,6 +83,10 @@ BuildRequires: libcurl-devel BuildRequires: libv4l-devel BuildRequires: ffmpeg-devel +# Required for mp4 container support +BuildRequires: libmp4v2-devel +BuildRequires: x264-devel + %{?with_nginx:Requires: nginx} %{?with_nginx:Requires: fcgiwrap} %{?with_nginx:Requires: php-fpm} From 464b588f0873041fa52d4f6a02b6fdb4284296ac Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Feb 2018 07:29:49 -0800 Subject: [PATCH 015/375] add a case for toggle, which are booleans and default them to false --- web/includes/functions.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/web/includes/functions.php b/web/includes/functions.php index b85624335..4e94b2f7e 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -641,6 +641,7 @@ function getFormChanges( $values, $newValues, $types=false, $columns=false ) { if ( !isset($types[$key]) ) $types[$key] = false; + switch( $types[$key] ) { case 'set' : { @@ -702,6 +703,16 @@ function getFormChanges( $values, $newValues, $types=false, $columns=false ) { } break; } + case 'toggle' : + if ( (!isset($values[$key])) or $values[$key] != $value ) { + if ( empty($value) ) { + $changes[$key] = "$key = 0"; + } else { + $changes[$key] = "$key = 0"; + //$changes[$key] = $key . ' = '.dbEscape(trim($value)); + } + } + break; default : { if ( !isset($values[$key]) || ($values[$key] != $value) ) { From c6f632325e459005b7b37c8f49cbe62254e54175 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Feb 2018 07:31:22 -0800 Subject: [PATCH 016/375] create an object for Controls entries, with appropriate defaults --- web/includes/Control.php | 228 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 web/includes/Control.php diff --git a/web/includes/Control.php b/web/includes/Control.php new file mode 100644 index 000000000..343a7b31a --- /dev/null +++ b/web/includes/Control.php @@ -0,0 +1,228 @@ + 0, + 'CanMoveDiag' => 0, + 'CanMoveMap' => 0, + 'CanMoveAbs' => 0, + 'CanMoveRel' => 0, + 'CanMoveCon' => 0, + 'CanPan' => 0, + 'MinPanRange' => NULL, + 'MaxPanRange' => NULL, + 'MinPanStep' => NULL, + 'MaxPanStep' => NULL, + 'HasPanSpeed' => 0, + 'MinPanSpeed' => NULL, + 'MaxPanSpeed' => NULL, + 'HasTurboPan' => 0, + 'TurboPanSpeed' => NULL, + 'CanTilt' => 0, + 'MinTiltRange' => NULL, + 'MaxTiltRange' => NULL, + 'MinTiltStep' => NULL, + 'MaxTiltStep' => NULL, + 'HasTiltSpeed' => 0, + 'MinTiltSpeed' => NULL, + 'MaxTiltSpeed' => NULL, + 'HasTurboTilt' => 0, + 'TurboTiltSpeed' => NULL, + 'CanZoom' => 0, + 'CanZoomAbs' => 0, + 'CanZoomRel' => 0, + 'CanZoomCon' => 0, + 'MinZoomRange' => NULL, + 'MaxZoomRange' => NULL, + 'MinZoomStep' => NULL, + 'MaxZoomStep' => NULL, + 'HasZoomSpeed' => 0, + 'MinZoomSpeed' => NULL, + 'MaxZoomSpeed' => NULL, + 'CanFocus' => 0, + 'CanAutoFocus' => 0, + 'CanFocusAbs' => 0, + 'CanFocusRel' => 0, + 'CanFocusCon' => 0, + 'MinFocusRange' => NULL, + 'MaxFocusRange' => NULL, + 'MinFocusStep' => NULL, + 'MaxFocusStep' => NULL, + 'HasFocusSpeed' => 0, + 'MinFocusSpeed' => NULL, + 'MaxFocusSpeed' => NULL, + 'CanIris' => 0, + 'CanAutoIris' => 0, + 'CanIrisAbs' => 0, + 'CanIrisRel' => 0, + 'CanIrisCon' => 0, + 'MinIrisRange' => NULL, + 'MaxIrisRange' => NULL, + 'MinIrisStep' => NULL, + 'MaxIrisStep' => NULL, + 'HasIrisSpeed' => 0, + 'MinIrisSpeed' => NULL, + 'MaxIrisSpeed' => NULL, + 'CanGain' => 0, + 'CanAutoGain' => 0, + 'CanGainAbs' => 0, + 'CanGainRel' => 0, + 'CanGainCon' => 0, + 'MinGainRange' => NULL, + 'MaxGainRange' => NULL, + 'MinGainStep' => NULL, + 'MaxGainStep' => NULL, + 'HasGainSpeed' => 0, + 'MinGainSpeed' => NULL, + 'MaxGainSpeed' => NULL, + 'CanWhite' => 0, + 'CanAutoWhite' => 0, + 'CanWhiteAbs' => 0, + 'CanWhiteRel' => 0, + 'CanWhiteCon' => 0, + 'MinWhiteRange' => NULL, + 'MaxWhiteRange' => NULL, + 'MinWhiteStep' => NULL, + 'MaxWhiteStep' => NULL, + 'HasWhiteSpeed' => 0, + 'MinWhiteSpeed' => NULL, + 'MaxWhiteSpeed' => NULL, + 'HasPresets' => 0, + 'NumPresets' => 0, + 'HasHomePreset' => 0, + 'CanSetPresets' => 0, + 'Name' => 'New', + 'Type' => 'Local', + 'Protocol' => NULL + ); + + public function __construct( $IdOrRow = NULL ) { + if ( $IdOrRow ) { + $row = NULL; + if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) { + $row = dbFetchOne( 'SELECT * FROM Control WHERE Id=?', NULL, array( $IdOrRow ) ); + if ( ! $row ) { + Error("Unable to load Control record for Id=" . $IdOrRow ); + } + } elseif ( is_array( $IdOrRow ) ) { + $row = $IdOrRow; + } else { + Error("Unknown argument passed to Control Constructor ($IdOrRow)"); + return; + } + + if ( $row ) { + foreach ($row as $k => $v) { + $this->{$k} = $v; + } + } else { + Error('No row for Control ' . $IdOrRow ); + } + } # end if isset($IdOrRow) + } // end function __construct + + public function __call($fn, array $args){ + if ( count($args) ) { + $this->{$fn} = $args[0]; + } + if ( array_key_exists($fn, $this) ) { + return $this->{$fn}; + #array_unshift($args, $this); + #call_user_func_array( $this->{$fn}, $args); + } else { + if ( array_key_exists($fn, $this->control_fields) ) { + return $this->control_fields{$fn}; + } else if ( array_key_exists( $fn, $this->defaults ) ) { + return $this->defaults{$fn}; + } else { + $backTrace = debug_backtrace(); + $file = $backTrace[1]['file']; + $line = $backTrace[1]['line']; + Warning( "Unknown function call Control->$fn from $file:$line" ); + } + } + } + + public function set( $data ) { + foreach ($data as $k => $v) { + if ( is_array( $v ) ) { + # perhaps should turn into a comma-separated string + $this->{$k} = implode(',',$v); + } else if ( is_string( $v ) ) { + $this->{$k} = trim( $v ); + } else if ( is_integer( $v ) ) { + $this->{$k} = $v; + } else if ( is_bool( $v ) ) { + $this->{$k} = $v; + } else { + Error( "Unknown type $k => $v of var " . gettype( $v ) ); + $this->{$k} = $v; + } + } + } + public static function find_all( $parameters = null, $options = null ) { + $filters = array(); + $sql = 'SELECT * FROM Controls '; + $values = array(); + + if ( $parameters ) { + $fields = array(); + $sql .= 'WHERE '; + foreach ( $parameters as $field => $value ) { + if ( $value == null ) { + $fields[] = $field.' IS NULL'; + } else if ( is_array( $value ) ) { + $func = function(){return '?';}; + $fields[] = $field.' IN ('.implode(',', array_map( $func, $value ) ). ')'; + $values += $value; + + } else { + $fields[] = $field.'=?'; + $values[] = $value; + } + } + $sql .= implode(' AND ', $fields ); + } + if ( $options and isset($options['order']) ) { + $sql .= ' ORDER BY ' . $options['order']; + } + $result = dbQuery($sql, $values); + $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Control'); + foreach ( $results as $row => $obj ) { + $filters[] = $obj; + } + return $filters; + } + + public function save( $new_values = null ) { + + if ( $new_values ) { + foreach ( $new_values as $k=>$v ) { + $this->{$k} = $v; + } + } + foreach ( $this->defaults as $k=>$v ) { + if ( ( ! array_key_exists( $k, $this ) ) or ( $this->{$k} == '' ) ) { + $this->{$k} = $v; + } + } + + $fields = array_keys( $this->defaults ); + +if ( array_key_exists( 'Id', $this ) ) { + $sql = 'UPDATE Controls SET '.implode(', ', array_map( function($field) {return $field.'=?';}, $fields ) ) . ' WHERE Id=?'; + $values = array_map( function($field){return $this->{$field};}, $fields ); + $values[] = $this->{'Id'}; + dbQuery( $sql, $values ); +} else { + $sql = 'INSERT INTO Controls SET '.implode(', ', array_map( function($field) {return $field.'=?';}, $fields ) ) . ''; + $values = array_map( function($field){return $this->{$field};}, $fields ); + dbQuery( $sql, $values ); +} + } // end function save + +} // end class Control +?> From bfbefc4c32888b188a390d38e26868222fd211b8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Feb 2018 07:31:48 -0800 Subject: [PATCH 017/375] Use our new Control object to do the saving instead of a generic function --- web/includes/actions.php | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/web/includes/actions.php b/web/includes/actions.php index ad9e03ce5..e01801e55 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -249,34 +249,12 @@ if ( !empty($action) ) { // Control capability actions, require control edit permissions if ( canEdit( 'Control' ) ) { if ( $action == 'controlcap' ) { - if ( !empty($_REQUEST['cid']) ) { - $control = dbFetchOne( 'SELECT * FROM Controls WHERE Id = ?', NULL, array($_REQUEST['cid']) ); - } else { - $control = array(); - } + require_once( 'Control.php' ); + $Control = new Control( !empty($_REQUEST['cid']) ? $_REQUEST['cid'] : null ); - // Define a field type for anything that's not simple text equivalent - $types = array( - // Empty - ); - - $columns = getTableColumns( 'Controls' ); - foreach ( $columns as $name=>$type ) { - if ( preg_match( '/^(Can|Has)/', $name ) ) { - $types[$name] = 'toggle'; - } - } - $changes = getFormChanges( $control, $_REQUEST['newControl'], $types, $columns ); - - if ( count( $changes ) ) { - if ( !empty($_REQUEST['cid']) ) { - dbQuery( "update Controls set ".implode( ", ", $changes )." where Id = ?", array($_REQUEST['cid']) ); - } else { - dbQuery( "insert into Controls set ".implode( ", ", $changes ) ); - //$_REQUEST['cid'] = dbInsertId(); - } - $refreshParent = true; - } + //$changes = getFormChanges( $control, $_REQUEST['newControl'], $types, $columns ); + $Control->save( $_REQUEST['newControl'] ); + $refreshParent = true; $view = 'none'; } elseif ( $action == 'delete' ) { if ( isset($_REQUEST['markCids']) ) { From 79037f56c13debdd81c69ac4ef1c2d35e2ac1019 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 26 Feb 2018 10:41:29 -0600 Subject: [PATCH 018/375] buildsystem - fix 32bit rpm builds --- utils/packpack/setarch.patch | 57 +++++++++++++++++++++++++++++++++ utils/packpack/startpackpack.sh | 6 ++++ 2 files changed, 63 insertions(+) create mode 100644 utils/packpack/setarch.patch diff --git a/utils/packpack/setarch.patch b/utils/packpack/setarch.patch new file mode 100644 index 000000000..4f196ec86 --- /dev/null +++ b/utils/packpack/setarch.patch @@ -0,0 +1,57 @@ +From 62a98b36fd62d328956503bc9427ae128bb811af Mon Sep 17 00:00:00 2001 +From: Andrew Bauer +Date: Mon, 26 Feb 2018 10:05:02 -0600 +Subject: [PATCH] fix 32bit rpm builds + +--- + pack/rpm.mk | 2 +- + packpack | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/packpack/pack/rpm.mk b/packpack/pack/rpm.mk +index c74e942..9a6b016 100644 +--- a/packpack/pack/rpm.mk ++++ b/packpack/pack/rpm.mk +@@ -124,7 +124,7 @@ package: $(BUILDDIR)/$(RPMSRC) + @echo "-------------------------------------------------------------------" + @echo "Building RPM packages" + @echo "-------------------------------------------------------------------" +- rpmbuild \ ++ setarch $(ARCH) rpmbuild \ + --define '_topdir $(BUILDDIR)' \ + --define '_sourcedir $(BUILDDIR)' \ + --define '_specdir $(BUILDDIR)' \ +diff --git a/packpack/packpack b/packpack/packpack +index 6f4c80f..c329399 100755 +--- a/packpack/packpack ++++ b/packpack/packpack +@@ -125,7 +125,7 @@ chmod a+x ${BUILDDIR}/userwrapper.sh + # + # Save defined configuration variables to ./env file + # +-env | grep -E "^PRODUCT=|^VERSION=|^RELEASE=|^ABBREV=|^TARBALL_|^CHANGELOG_|^CCACHE_|^PACKAGECLOUD_|^SMPFLAGS=|^OS=|^DIST=" \ ++env | grep -E "^PRODUCT=|^VERSION=|^RELEASE=|^ABBREV=|^TARBALL_|^CHANGELOG_|^CCACHE_|^PACKAGECLOUD_|^SMPFLAGS=|^OS=|^DIST=|^ARCH=" \ + > ${BUILDDIR}/env + + # +diff --git a/packpack/packpack b/packpack/packpack +index c329399..6ffaa9c 100755 +--- a/packpack/packpack ++++ b/packpack/packpack +@@ -19,11 +19,11 @@ DOCKER_REPO=${DOCKER_REPO:-packpack/packpack} + if [ -z "${ARCH}" ]; then + # Use uname -m instead of HOSTTYPE + case "$(uname -m)" in +- i*86) ARCH="i386" ;; +- arm*) ARCH="armhf" ;; +- x86_64) ARCH="x86_64"; ;; +- aarch64) ARCH="aarch64" ;; +- *) ARCH="${HOSTTYPE}" ;; ++ i*86) export ARCH="i386" ;; ++ arm*) export ARCH="armhf" ;; ++ x86_64) export ARCH="x86_64"; ;; ++ aarch64) export ARCH="aarch64" ;; ++ *) export ARCH="${HOSTTYPE}" ;; + esac + fi + diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh index 146399690..6e1cff817 100755 --- a/utils/packpack/startpackpack.sh +++ b/utils/packpack/startpackpack.sh @@ -114,6 +114,12 @@ commonprep () { patch -p1 < utils/packpack/nolintian.patch fi + # fix 32bit rpm builds + patch --dry-run --silent -f -p1 < utils/packpack/setarch.patch + if [ $? -eq 0 ]; then + patch -p1 < utils/packpack/setarch.patch + fi + # The rpm specfile requires we download the tarball and manually move it into place # Might as well do this for Debian as well, rather than git submodule init CRUDVER="3.0.10" From 9d1a8b1e18ed5ce426b50cb9bd03358e78927e90 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Feb 2018 10:39:45 -0800 Subject: [PATCH 019/375] Add the danger css tag to cpuload > 5, freeram < 10% and freeswap < 10% --- web/skins/classic/views/options.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index 2a38dbbd4..4375081c4 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -223,11 +223,17 @@ foreach( array_map( 'basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI - + - - - + + + From 92c34f60435b640337782e6fe7f99f6048ef28d3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Feb 2018 16:09:36 -0800 Subject: [PATCH 020/375] add Groups to monitor edit --- web/skins/classic/views/monitor.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index e057732b2..d4758ae66 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -726,6 +726,9 @@ switch ( $tab ) { + Type() != 'Local' && $monitor->Type() != 'File' && $monitor->Type() != 'NVSocket' ) { From 944298428a1815c7f9f02fd55292fa626f273b6f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Feb 2018 16:10:10 -0800 Subject: [PATCH 021/375] break out get_groups_dropdown to call a function called get_dropdown_options to populate thje options --- web/includes/Group.php | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/web/includes/Group.php b/web/includes/Group.php index ee86a320c..f8836ebca 100644 --- a/web/includes/Group.php +++ b/web/includes/Group.php @@ -135,7 +135,7 @@ public $defaults = array( return $this->{'MonitorIds'}; } - public static function get_group_dropdown() { + public static function get_group_dropdown( ) { session_start(); $selected_group_id = 0; @@ -148,13 +148,23 @@ public $defaults = array( } session_write_close(); + return htmlSelect( 'Group[]', Group::get_dropdown_options(), isset($_SESSION['Group'])?$_SESSION['Group']:null, array( + 'onchange' => 'this.form.submit();', + 'class'=>'chosen', + 'multiple'=>'multiple', + 'data-placeholder'=>'All', + ) ); + + } # end public static function get_group_dropdown + + public static function get_dropdown_options() { $Groups = array(); foreach ( Group::find_all( ) as $Group ) { $Groups[$Group->Id()] = $Group; } # This array is indexed by parent_id -global $children; + global $children; $children = array(); foreach ( $Groups as $id=>$Group ) { @@ -181,16 +191,10 @@ global $children; $group_options += get_options( $Group ); } } - return htmlSelect( 'Group[]', $group_options, isset($_SESSION['Group'])?$_SESSION['Group']:null, array( - 'onchange' => 'this.form.submit();', - 'class'=>'chosen', - 'multiple'=>'multiple', - 'data-placeholder'=>'All', - ) ); + return $group_options; + } - } # end public static function get_group_dropdown - - public static function get_group_dropdowns() { + public static function get_group_dropdowns( $selected = null ) { # This will end up with the group_id of the deepest selection $group_id = 0; $depth = 0; @@ -205,6 +209,7 @@ global $children; break; $parent_group_ids = array(); +if ( ! $selected ) { $selected_group_id = 0; if ( isset($_REQUEST['group'.$depth]) ) { $selected_group_id = $group_id = $_SESSION['group'.$depth] = $_REQUEST['group'.$depth]; @@ -213,6 +218,9 @@ global $children; } else if ( isset($_REQUEST['filtering']) ) { unset($_SESSION['group'.$depth]); } +} else { + $selected_group_id = $selected; +} foreach ( $Groups as $Group ) { if ( ! isset( $groups[$depth] ) ) { From 902f5f098a04ec1f3470aed7408fb5376d6efdbe Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Feb 2018 16:10:27 -0800 Subject: [PATCH 022/375] remove debug code --- src/zm_ffmpeg_camera.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index 4c7d273c1..c43bb3389 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -171,7 +171,6 @@ int FfmpegCamera::PrimeCapture() { } int FfmpegCamera::PreCapture() { - Debug(1, "PreCapture"); // If Reopen was called, then ffmpeg is closed and we need to reopen it. if ( ! mCanCapture ) return OpenFfmpeg(); From 3586825c908c3139ff0fc4aeec93c94a030cebe2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Feb 2018 17:08:05 -0800 Subject: [PATCH 023/375] fix preevent_count==0 causing div/0 --- src/zm_monitor.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index e149a78f6..58e758577 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1202,19 +1202,20 @@ bool Monitor::Analyse() { gettimeofday( &now, NULL ); if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) { + if ( now.tv_sec != last_fps_time ) { + double new_fps = double(fps_report_interval)/(now.tv_sec - last_fps_time); + Info("%s: %d - Analysing at %.2f fps", name, image_count, new_fps); + if ( fps != new_fps ) { + fps = new_fps; + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf(sql, sizeof(sql), "INSERT INTO Monitor_Status (MonitorId,AnalysisFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE AnalysisFPS = %.2lf", id, fps, fps); + if ( mysql_query(&dbconn, sql) ) { + Error("Can't run query: %s", mysql_error(&dbconn)); + } + } // end if fps != new_fps - double new_fps = double(fps_report_interval)/(now.tv_sec - last_fps_time); - Info("%s: %d - Analysing at %.2f fps", name, image_count, new_fps); - if ( fps != new_fps ) { - fps = new_fps; - static char sql[ZM_SQL_SML_BUFSIZ]; - snprintf(sql, sizeof(sql), "INSERT INTO Monitor_Status (MonitorId,AnalysisFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE AnalysisFPS = %.2lf", id, fps, fps); - if ( mysql_query(&dbconn, sql) ) { - Error("Can't run query: %s", mysql_error(&dbconn)); - } - } // end if fps != new_fps - - last_fps_time = now.tv_sec; + last_fps_time = now.tv_sec; + } } int index; @@ -1690,7 +1691,7 @@ bool Monitor::Analyse() { //shared_data->last_read_time = image_buffer[index].timestamp->tv_sec; shared_data->last_read_time = now.tv_sec; - if ( analysis_fps ) { + if ( analysis_fps && pre_event_buffer_count ) { // If analysis fps is set, add analysed image to dedicated pre event buffer int pre_index = image_count%pre_event_buffer_count; pre_event_buffer[pre_index].image->Assign(*snap->image); From 735e36c2a8ee07af755c93c1db875d15ab410108 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Feb 2018 17:08:30 -0800 Subject: [PATCH 024/375] split htmlSelect into htmlOptions --- web/includes/functions.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/web/includes/functions.php b/web/includes/functions.php index 0f003801e..b2b08cca1 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -553,20 +553,19 @@ function htmlSelect( $name, $contents, $values, $behaviours=false ) { } } - $html = "".htmlOptions( $contents, $values ).''; +} + +function htmlOptions( $contents, $values ) { + $html = ''; foreach ( $contents as $value=>$text ) { if ( is_array( $text ) ) $text = $text['Name']; else if ( is_object( $text ) ) $text = $text->Name(); - //for ( $i = 0; $i < count($contents); $i +=2 ) { - //$value = $contents[$i]; - //$text = $contents[$i+1]; $selected = is_array( $values ) ? in_array( $value, $values ) : !strcmp($value, $values); - //Warning("Selected is $selected from $value and $values"); $html .= ""; } - $html .= ''; return $html; } From 793e87c26d109ff84421c3f9dd303f9be0794896 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Feb 2018 17:57:50 -0800 Subject: [PATCH 025/375] Apply chosen style to group and linked monitors dropdown --- web/skins/classic/views/monitor.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index d4758ae66..67d0a8413 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -708,7 +708,7 @@ switch ( $tab ) { - LinkedMonitors() ) @@ -1018,4 +1018,7 @@ if ( $monitor->Type() == 'Local' ) { + From 6a6eb8768633f557b4e638e7aac32f9a6238f59f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Feb 2018 18:00:02 -0800 Subject: [PATCH 026/375] fix defaults --- web/skins/classic/views/monitor.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 67d0a8413..2815b2da8 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -89,12 +89,12 @@ if ( ! $monitor ) { 'Pass' => '', 'Colours' => 4, 'Palette' => 0, - 'Width' => '1280', - 'Height' => '962', + 'Width' => '', + 'Height' => '', 'Orientation' => '0', 'Deinterlacing' => 0, 'RTSPDescribe' => 0, - 'SaveJPEGs' => '4', + 'SaveJPEGs' => '0', 'VideoWriter' => '1', 'EncoderParameters' => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n", 'RecordAudio' => '0', @@ -102,9 +102,9 @@ if ( ! $monitor ) { 'LabelX' => 0, 'LabelY' => 0, 'LabelSize' => 1, - 'ImageBufferCount' => 40, - 'WarmupCount' => 1, - 'PreEventCount' => 1, + 'ImageBufferCount' => 20, + 'WarmupCount' => 0, + 'PreEventCount' => 0, 'PostEventCount' => 5, 'StreamReplayBuffer' => 0, 'AlarmFrameCount' => 1, From 67cc7dcf7c5c89945be503a2ca814a40090f1cc5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 27 Feb 2018 11:19:20 -0800 Subject: [PATCH 027/375] Add a GroupIds function to return the groups --- web/includes/Monitor.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index 6fb19c1ed..46de04aaa 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -392,5 +392,15 @@ Logger::Debug("sending command to $url"); } } // end if we are on the recording server } + public function GroupIds( ) { + if ( !array_key_exists('GroupIds', $this) ) { + if ( array_key_exists('Id', $this) and $this->{'Id'} ) { + $this->{'GroupIds'} = dbFetchAll( 'SELECT GroupId FROM Groups_Monitors WHERE MonitorId=?', 'GroupId', array($this->{'Id'}) ); + } else { + $this0->{'GroupIds'} = array(); + } + } + return $this->{'GroupIds'}; + } } // end class Monitor ?> From 0312dc3c2d2bae560b1a3316de439bc5b12df140 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 27 Feb 2018 11:19:44 -0800 Subject: [PATCH 028/375] Add Group saving to Monitor saving --- web/includes/actions.php | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/web/includes/actions.php b/web/includes/actions.php index 3676a88b9..a5d615caf 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -471,7 +471,7 @@ if ( canEdit( 'Monitors' ) ) { $mid = 0; if ( !empty($_REQUEST['mid']) ) { $mid = validInt($_REQUEST['mid']); - $monitor = dbFetchOne( 'SELECT * FROM Monitors WHERE Id = ?', NULL, array($mid) ); + $monitor = dbFetchOne( 'SELECT * FROM Monitors WHERE Id=?', NULL, array($mid) ); if ( ZM_OPT_X10 ) { $x10Monitor = dbFetchOne( 'SELECT * FROM TriggersX10 WHERE MonitorId=?', NULL, array($mid) ); @@ -484,6 +484,7 @@ if ( canEdit( 'Monitors' ) ) { $x10Monitor = array(); } } + $Monitor = new Monitor( $monitor ); // Define a field type for anything that's not simple text equivalent $types = array( @@ -519,6 +520,7 @@ if ( canEdit( 'Monitors' ) ) { zmaControl( $monitor, 'stop' ); zmcControl( $monitor, 'stop' ); dbQuery( 'UPDATE Monitors SET '.implode( ', ', $changes ).' WHERE Id=?', array($mid) ); + // Groups will be added below if ( isset($changes['Name']) or isset($changes['StorageId']) ) { $OldStorage = new Storage( $monitor['StorageId'] ); $saferOldName = basename( $monitor['Name'] ); @@ -578,16 +580,25 @@ if ( canEdit( 'Monitors' ) ) { mkdir( $Storage->Path().'/'.$mid, 0755 ); $saferName = basename($_REQUEST['newMonitor']['Name']); symlink( $mid, $Storage->Path().'/'.$saferName ); - if ( isset($_COOKIE['zmGroup']) ) { - dbQuery( 'INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($_COOKIE['zmGroup'],$mid) ); - } + } else { Error("Error saving new Monitor."); return; } } else { Error("Users with Monitors restrictions cannot create new monitors."); + return; } + if ( count($_POST['newMonitor']['GroupIds']) != count($Monitor->GroupIds()) or array_diff($_POST['newMonitor']['GroupIds'], $Monitor->GroupIds() ) ) { + if ( $Monitor->Id() ) + dbQuery('DELETE FROM Groups_Monitors WHERE MonitorId=?', null, array($Mid)); + + if ( isset($_POST['newMonitor']['GroupIds']) ) { + foreach ( $_POST['newMonitor']['GroupIds'] as $group_id ) { + dbQuery( 'INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($group_id, $mid) ); + } + } + } // end if there has been a change of groups $restart = true; } # end if count(changes) From c50627fd882923c5c1e29059473447110f112b8c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 27 Feb 2018 11:20:03 -0800 Subject: [PATCH 029/375] GroupIds needs to be an array --- web/skins/classic/views/monitor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 2815b2da8..17f6eb584 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -726,7 +726,7 @@ switch ( $tab ) { -GroupIds() ); ?> From 83fad681b306feb94981e9819031823a1bfdf5b8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 27 Feb 2018 11:49:13 -0800 Subject: [PATCH 030/375] use button tags and hide the button content after click --- web/skins/classic/views/monitor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 17f6eb584..d2d416852 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -1011,8 +1011,8 @@ if ( $monitor->Type() == 'Local' ) {
- disabled="disabled"/> - + +
From c5eec7e2fd4b35fa866daca923044186dea93f3d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 27 Feb 2018 15:10:20 -0800 Subject: [PATCH 031/375] hide save button on successful form completion so we don't get a duplicate submit --- web/skins/classic/views/monitor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index d2d416852..98d68f62b 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -519,7 +519,7 @@ foreach ( $tabs as $name=>$value ) { ?>
-
+ @@ -1011,7 +1011,7 @@ if ( $monitor->Type() == 'Local' ) {
- +
From 5ac003d448f6671590e0b235125cfc48792a9a5d Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 27 Feb 2018 17:39:58 -0600 Subject: [PATCH 032/375] Update packpack.rst --- docs/installationguide/packpack.rst | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/docs/installationguide/packpack.rst b/docs/installationguide/packpack.rst index 8e52ad876..377af68f5 100644 --- a/docs/installationguide/packpack.rst +++ b/docs/installationguide/packpack.rst @@ -1,4 +1,4 @@ -All Distros - A Simpler Way to Build ZoneMinder +All Distros - A Docker Way to Build ZoneMinder =============================================== .. contents:: @@ -27,6 +27,8 @@ Procedure - If the desired distro does not appear in either list, then unfortuantely you cannot use the procedure described here. +- If the desired distro architecture is arm, refer to Appendix A to enable qemu emulation on your amd64 host machine. + **Step 2:** Install Docker. You need to have a working installation of Docker so head over to the `Docker site `_ and get it working. Before continuing to the next step, verify you can run the Docker "Hello World" container as a normal user. To run a Docker container as a normal user, issue the following: @@ -99,7 +101,27 @@ For advanced users who really want to go out into uncharted waters, it is theore Building arm packages in this manner has not been tested by us, however. +Appendix A - Enable Qemu On the Host +------------------------------------ +If you intend to build ZoneMinder packages for arm on an amd64 host, then Debian users can following these steps to enable transparent Qemu emulation: +:: + sudo apt-get install binfmt-support qemu qemu-user-static +Verify arm emulation is enabled by issuing: + +:: + + sudo update-binfmts --enable qemu-arm + +You may get an message stating emulation for this processor is already enabled. + +More testing needs to be done for Redhat distros but it appears Fedora users can just run: + +:: + + sudo systemctl start systemd-binfmt + +TO-DO: Verify the details behind enabling qemu emulation on redhat distros. Pull requests are welcome. From 35c63ac0bce00fbafdceab569c358142c7ecf0e8 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 27 Feb 2018 17:43:36 -0600 Subject: [PATCH 033/375] Update packpack.rst --- docs/installationguide/packpack.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installationguide/packpack.rst b/docs/installationguide/packpack.rst index 377af68f5..6f4355839 100644 --- a/docs/installationguide/packpack.rst +++ b/docs/installationguide/packpack.rst @@ -27,7 +27,7 @@ Procedure - If the desired distro does not appear in either list, then unfortuantely you cannot use the procedure described here. -- If the desired distro architecture is arm, refer to Appendix A to enable qemu emulation on your amd64 host machine. +- If the desired distro architecture is arm, refer to `Appendix A - Enable Qemu On the Host`_ to enable qemu emulation on your amd64 host machine. **Step 2:** Install Docker. From 7fed5fd596d5a0af6232d4e3ec6a8861f0d52343 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 27 Feb 2018 19:46:44 -0600 Subject: [PATCH 034/375] spelling --- docs/installationguide/packpack.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installationguide/packpack.rst b/docs/installationguide/packpack.rst index 6f4355839..dd54ef4b2 100644 --- a/docs/installationguide/packpack.rst +++ b/docs/installationguide/packpack.rst @@ -116,7 +116,7 @@ Verify arm emulation is enabled by issuing: sudo update-binfmts --enable qemu-arm -You may get an message stating emulation for this processor is already enabled. +You may get a message stating emulation for this processor is already enabled. More testing needs to be done for Redhat distros but it appears Fedora users can just run: From dc074bd2c00c5fc1e23722d2747c5a177c68b0c4 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Feb 2018 07:18:38 -0800 Subject: [PATCH 035/375] fix path to triggers.sql --- db/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/CMakeLists.txt b/db/CMakeLists.txt index fda03b463..c68285e5b 100644 --- a/db/CMakeLists.txt +++ b/db/CMakeLists.txt @@ -13,4 +13,4 @@ install(FILES ${dbfileslist} DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zm_create.sql" DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db") # install triggers.sql -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/triggers.sql" DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/triggers.sql" DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db") From 0077f2e17bbd6f34e6822c5ac4c1e42fa9e868db Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Feb 2018 11:06:28 -0500 Subject: [PATCH 036/375] Update faq.rst I see no reason to mention bits. No one cares about bits. Our base unit should be bytes. Also, lets be consistent and use 1024 as the divisor when converting to Kb and Mb and Gb. --- docs/faq.rst | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 87421ddb9..d6694b153 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -71,22 +71,22 @@ The 1.2 at the start is basically adding 20% on top of the calculation to accoun The math breakdown for 4 cameras running at 1280x960 capture, 50 frame buffer, 24 bit color space: :: - 1280*960 = 1,228,800 (bits) - 1,228,800 * 24 = 2,359,296,000 (bits) - 2,359,296,000 * 50 = 5,898,240,000 (bits) - 5,898,240,000 * 4 = 7,077,888,000 (bits) - 7,077,888,000 / 8 = 884,736,000 (bytes) - 884,736,000 / 1000 = 884,736 (Kilobytes) - 884,736 / 1000 = 864 (Megabytes) - 864 / 1000 = 0.9 (Gigabyte) + 1280*960 = 1,228,800 (bytes) + 1,228,800 * (3 bytes for 24 bit) = 3,686,400 (bytes) + 3,686,400 * 50 = 184,320,000 (bytes) + 184,320,000 * 4 = 737,280,000 (bytes) + 737,280,000 / 1024 = 720,000 (Kilobytes) + 720,000 / 1024 = 703.125 (Megabytes) + 703.125 / 1024 = 0.686 (Gigabytes) -Around 900MB of memory. +Around 700MB of memory. So if you have 2GB of memory, you should be all set. Right? **Not, really**: * This is just the base memory required to capture the streams. Remember ZM is always capturing streams irrespective of whether you are actually recording or not - to make sure its image ring buffer is there with pre images when an alarm kicks in. * You also need to account for other processes not related to ZM running in your box * You also need to account for other ZM processes - for example, I noticed the audit daemon takes up a good amount of memory when it runs, DB updates also take up memory + * If you are using H264 encoding, that buffers a lot of frames in memory as well. So a good rule of thumb is to make sure you have twice the memory as the calculation above (and if you are using the ZM server for other purposes, please factor in those memory requirements as well) @@ -128,15 +128,14 @@ So, for example: :: 384x288 capture resolution, that makes: 110 592 pixels - in 24 bit color that's x24 = 2 654 208 bits per frame - by 80 frames ring buffer x80 = 212 336 640 bits per camera - by 4 cameras x4 = 849 346 560 bits. - Plus 10% overhead = 934 281 216 bits - That's 116 785 152 bytes, and - = 114 048 kB, respectively 111.38 MB. - If my shared memory is set to 134 217 728, which is exactly 128MB, + in 24 bit color that's x 3 = 331,776 bytes per frame + by 80 frames ring buffer x80 = 26,542,080 bytes per camera + by 4 cameras x4 = 106,168,320 bytes. + Plus 10% overhead = 116,785,152 bytes + Thats 114,048 kB, respectively 111.38 MB. + If my shared memory is set to 134,217,728, which is exactly 128MB, that means I shouldn't have any problem. - (Note that 1 byte = 8 bits and 1kbyte = 1024bytes, 1MB = 1024 kB) + (Note that 1kbyte = 1024bytes, 1MB = 1024 kB) If for instance you were using 24bit 640x480 then this would come to about 92Mb if you are using the default buffer size of 100. If this is too large then you can either reduce the image or buffer sizes or increase the maximum amount of shared memory available. If you are using RedHat then you can get details on how to change these settings `here `__ From 865649d785378d68c78b639505f2419b1fae38ac Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 1 Mar 2018 19:20:00 -0800 Subject: [PATCH 037/375] Turn on c++11 --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b8308afc..d39c97d4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,7 @@ if(NOT HOST_OS) "ZoneMinder was unable to deterimine the host OS. Please report this. Value of CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") endif(NOT HOST_OS) +set (CMAKE_CXX_STANDARD 11) # Default CLFAGS and CXXFLAGS: set(CMAKE_C_FLAGS_RELEASE "-Wall -D__STDC_CONSTANT_MACROS -O2") set(CMAKE_CXX_FLAGS_RELEASE "-Wall -D__STDC_CONSTANT_MACROS -O2") From b3d23ab2337c8697c7984ada47bbfaa1e97964bb Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 1 Mar 2018 19:20:29 -0800 Subject: [PATCH 038/375] merge zma_to_thread version of db functions, which include a mutex lock --- src/zm_db.cpp | 25 +++++++++++++++++-------- src/zm_db.h | 35 ++++++++++++++--------------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/zm_db.cpp b/src/zm_db.cpp index fb716349e..fc5ee5fe0 100644 --- a/src/zm_db.cpp +++ b/src/zm_db.cpp @@ -23,29 +23,35 @@ #include "zm.h" #include "zm_db.h" +// From what I read, we need one of these per thread MYSQL dbconn; +Mutex db_mutex; -int zmDbConnected = false; +bool zmDbConnected = false; -void zmDbConnect() { +bool zmDbConnect() { // For some reason having these lines causes memory corruption and crashing on newer debian/ubuntu //if ( zmDbConnected ) //return; if ( !mysql_init( &dbconn ) ) { Error( "Can't initialise database connection: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + return false; } my_bool reconnect = 1; if ( mysql_options( &dbconn, MYSQL_OPT_RECONNECT, &reconnect ) ) - Fatal( "Can't set database auto reconnect option: %s", mysql_error( &dbconn ) ); + Error( "Can't set database auto reconnect option: %s", mysql_error( &dbconn) ); if ( !staticConfig.DB_SSL_CA_CERT.empty() ) - mysql_ssl_set( &dbconn, staticConfig.DB_SSL_CLIENT_KEY.c_str(), staticConfig.DB_SSL_CLIENT_CERT.c_str(), staticConfig.DB_SSL_CA_CERT.c_str(), NULL, NULL ); + mysql_ssl_set( &dbconn, + staticConfig.DB_SSL_CLIENT_KEY.c_str(), + staticConfig.DB_SSL_CLIENT_CERT.c_str(), + staticConfig.DB_SSL_CA_CERT.c_str(), + NULL, NULL ); std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":" ); if ( colonIndex == std::string::npos ) { if ( !mysql_real_connect( &dbconn, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, NULL, 0 ) ) { Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + return false; } } else { std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex ); @@ -53,12 +59,12 @@ void zmDbConnect() { if ( dbPortOrSocket[0] == '/' ) { if ( !mysql_real_connect( &dbconn, NULL, staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, dbPortOrSocket.c_str(), 0 ) ) { Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + return false; } } else { if ( !mysql_real_connect( &dbconn, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, atoi(dbPortOrSocket.c_str()), NULL, 0 ) ) { Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + return false; } } } @@ -67,6 +73,7 @@ void zmDbConnect() { exit( mysql_errno( &dbconn ) ); } zmDbConnected = true; + return zmDbConnected; } void zmDbClose() { @@ -84,6 +91,7 @@ MYSQL_RES * zmDbFetch( const char * query ) { Error( "Not connected." ); return NULL; } + db_mutex.lock(); if ( mysql_query( &dbconn, query ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); @@ -95,6 +103,7 @@ MYSQL_RES * zmDbFetch( const char * query ) { Error( "Can't use query result: %s for query %s", mysql_error( &dbconn ), query ); return NULL; } + db_mutex.unlock(); return result; } // end MYSQL_RES * zmDbFetch( const char * query ); diff --git a/src/zm_db.h b/src/zm_db.h index f9b158be8..267995e70 100644 --- a/src/zm_db.h +++ b/src/zm_db.h @@ -21,37 +21,30 @@ #define ZM_DB_H #include +#include "zm_thread.h" class zmDbRow { - private: - MYSQL_RES *result_set; - MYSQL_ROW row; - public: - zmDbRow() { result_set = NULL; row = NULL; }; - MYSQL_RES *fetch( const char *query ); - zmDbRow( MYSQL_RES *, MYSQL_ROW *row ); - ~zmDbRow(); + private: + MYSQL_RES *result_set; + MYSQL_ROW row; + public: + zmDbRow() { result_set = NULL; row = NULL; }; + MYSQL_RES *fetch( const char *query ); + zmDbRow( MYSQL_RES *, MYSQL_ROW *row ); + ~zmDbRow(); - char *operator[](unsigned int index) const { - return row[index]; - } + char *operator[](unsigned int index) const { + return row[index]; + } }; -#ifdef __cplusplus -extern "C" { -#endif extern MYSQL dbconn; +extern Mutex db_mutex; -extern int zmDbConnected; - -void zmDbConnect(); +bool zmDbConnect(); void zmDbClose(); MYSQL_RES * zmDbFetch( const char *query ); zmDbRow *zmDbFetchOne( const char *query ); -#ifdef __cplusplus -} /* extern "C" */ -#endif - #endif // ZM_DB_H From 1bc6e40fbc716d58c04fc90b37253e4467e299d5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 1 Mar 2018 19:20:52 -0800 Subject: [PATCH 039/375] add mutex locking around mysql functions so that we can go multi-threaded --- src/zm_event.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index c37bd04ce..17c385c87 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -96,11 +96,14 @@ Event::Event( monitor->GetOptSaveJPEGs(), storage->SchemeString().c_str() ); + db_mutex.lock(); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't insert event: %s. sql was (%s)", mysql_error( &dbconn ), sql ); - exit( mysql_errno( &dbconn ) ); + db_mutex.unlock(); + return; } id = mysql_insert_id( &dbconn ); + db_mutex.unlock(); if ( untimedEvent ) { Warning( "Event %d has zero time, setting to current", id ); } @@ -110,7 +113,6 @@ Event::Event( tot_score = 0; max_score = 0; - struct stat statbuf; char id_file[PATH_MAX]; if ( storage->Scheme() == Storage::DEEP ) { @@ -236,10 +238,11 @@ Event::~Event() { snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )", id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec ); + db_mutex.lock(); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't insert frame: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); } + db_mutex.unlock(); } /* Close the video file */ @@ -259,10 +262,11 @@ Event::~Event() { } snprintf( sql, sizeof(sql), "update Events set Name='%s%d', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo = '%s' where Id = %d", monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, video_name, id ); + db_mutex.lock(); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't update event: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); } + db_mutex.unlock(); } void Event::createNotes( std::string ¬es ) { @@ -427,9 +431,11 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) { mysql_real_escape_string( &dbconn, escapedNotes, notes.c_str(), notes.length() ); snprintf( sql, sizeof(sql), "update Events set Notes = '%s' where Id = %d", escapedNotes, id ); + db_mutex.lock(); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't insert event: %s", mysql_error( &dbconn ) ); } + db_mutex.unlock(); #endif } } @@ -490,9 +496,11 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st if ( frameCount ) { Debug( 1, "Adding %d/%d frames to DB", frameCount, n_frames ); *(sql+strlen(sql)-2) = '\0'; + db_mutex.lock(); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't insert frames: %s, sql was (%s)", mysql_error( &dbconn ), sql ); } + db_mutex.unlock(); last_db_frame = frames; } else { Debug( 1, "No valid pre-capture frames to add" ); @@ -542,10 +550,13 @@ Debug(3, "Writing video"); Debug( 1, "Adding frame %d of type \"%s\" to DB", frames, Event::frame_type_names[frame_type] ); static char sql[ZM_SQL_MED_BUFSIZ]; snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score ) values ( %d, %d, '%s', from_unixtime( %ld ), %s%ld.%02ld, %d )", id, frames, frame_type_names[frame_type], timestamp.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, score ); + db_mutex.lock(); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't insert frame: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + db_mutex.unlock(); + return; } + db_mutex.unlock(); last_db_frame = frames; // We are writing a Bulk frame @@ -560,10 +571,11 @@ Debug(3, "Writing video"); max_score, id ); + db_mutex.lock(); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't update event: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); } + db_mutex.unlock(); } } // end if db_frame From 4d81b7b66bb49b1f3e9536dfbceb627bcacbd049 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 1 Mar 2018 19:21:41 -0800 Subject: [PATCH 040/375] Do not just reconnect to the input stream on EOF. pts/dts gets outof whack when doing passthrough. Instead treat it as a loss of signal, which will end the event and start a new one --- src/zm_ffmpeg_camera.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index c43bb3389..fae261e65 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -710,20 +710,6 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event ret = av_read_frame( mFormatContext, &packet ); if ( ret < 0 ) { av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE ); - if ( - // Check if EOF. - (ret == AVERROR_EOF || (mFormatContext->pb && mFormatContext->pb->eof_reached)) || - // Check for Connection failure. - (ret == -110) - ) { - Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf); - if ( ReopenFfmpeg() < 0 ) { - // OpenFfmpeg will do enough logging. - return -1; - } - continue; - } - Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, ret, errbuf ); return -1; } From 28342b907b290b5967a2b7a40bcfcb77b0815343 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 1 Mar 2018 19:22:22 -0800 Subject: [PATCH 041/375] add a thread for deleting the event. This is because writing out the final frames of an mp4 can take a long time, during which we are not analyzing. --- src/zm_monitor.cpp | 17 +++++++++++++++-- src/zm_monitor.h | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 58e758577..0828b497a 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -326,7 +326,8 @@ Monitor::Monitor( zones( p_zones ), timestamps( 0 ), images( 0 ), - privacy_bitmask( NULL ) + privacy_bitmask( NULL ), + event_delete_thread(NULL) { strncpy( name, p_name, sizeof(name)-1 ); @@ -599,6 +600,11 @@ Debug(3, "Success connecting"); } Monitor::~Monitor() { + if ( event_delete_thread ) { + event_delete_thread->join(); + delete event_delete_thread; + event_delete_thread = NULL; + } if ( timestamps ) { delete[] timestamps; timestamps = 0; @@ -3100,7 +3106,14 @@ bool Monitor::closeEvent() { if ( function == RECORD || function == MOCORD ) { gettimeofday( &(event->EndTime()), NULL ); } - delete event; + if ( event_delete_thread ) { + event_delete_thread->join(); + delete event_delete_thread; + event_delete_thread = NULL; + } + event_delete_thread = new std::thread([](Event *event) { + delete event; + }, event ); video_store_data->recording = (struct timeval){0}; event = 0; return( true ); diff --git a/src/zm_monitor.h b/src/zm_monitor.h index 0de71c424..ff6ceca50 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -22,6 +22,7 @@ #include #include +#include #include "zm.h" #include "zm_coord.h" @@ -325,6 +326,7 @@ protected: Image **images; const unsigned char *privacy_bitmask; + std::thread *event_delete_thread; // Used to close events, but continue processing. int n_linked_monitors; MonitorLink **linked_monitors; From 9af6dc02bcb19f47ee0b79a5ee7eb68f0494319e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 1 Mar 2018 19:22:47 -0800 Subject: [PATCH 042/375] better debug of packet pts/dts/duration --- src/zm_videostore.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index e074b1d9d..0e72a7c7e 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -721,8 +721,10 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) { duration = av_rescale_q(ipkt->pts - video_last_pts, video_in_stream->time_base, video_out_stream->time_base); - Debug(1, "duration calc: pts(%d) - last_pts(%d) = (%d)", ipkt->pts, - video_last_pts, duration); + Debug(1, "duration calc: pts(%" PRId64 ") - last_pts(% " PRId64 ") = (%" PRId64 ")", + ipkt->pts, + video_last_pts, + duration); if (duration < 0) { duration = ipkt->duration; } From debe4607bc71ad3160ccc3bdb27853071b3d78cd Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 1 Mar 2018 19:23:03 -0800 Subject: [PATCH 043/375] add Parent and Parents functions --- web/includes/Group.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/web/includes/Group.php b/web/includes/Group.php index f8836ebca..d6edba7ca 100644 --- a/web/includes/Group.php +++ b/web/includes/Group.php @@ -288,6 +288,23 @@ $group_options[$Group->Id()] = str_repeat( ' ', $depth ) . $Group->Name(); return $monitor_id; } +public function Parent( ) { + if ( $this->{'ParentId'} ) { + return new Group($this->{'ParentId'}); + } + return null; +} + +public function Parents() { + $Parents = array(); + $Parent = $this->Parent(); + while( $Parent ) { + array_unshift($Parents, $Parent); + $Parent = $Parent->Parent(); + } + return $Parents; +} + } # end class Group From 9a157bf4cabdfaafcf3d5ea07aa7db36cd3dc62d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 1 Mar 2018 19:23:27 -0800 Subject: [PATCH 044/375] add Type, MaxFPS, AlarmMaxFPS to field defaults --- web/includes/Monitor.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index 46de04aaa..52031824c 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -17,6 +17,9 @@ private $defaults = array( 'AnalysisFPSLimit' => null, 'ZoneCount' => 0, 'Triggers' => null, + 'Type' => 'Ffmpeg', + 'MaxFPS' => null, + 'AlarmMaxFPS' => null, ); private $status_fields = array( 'AnalysisFPS' => null, From 7e628bc3fdf0aabe9f5aeba4d2dacc3a720681e7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 1 Mar 2018 19:23:46 -0800 Subject: [PATCH 045/375] add showing groups under Monitor Name on console --- web/skins/classic/views/console.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php index 846404b60..3afc05820 100644 --- a/web/skins/classic/views/console.php +++ b/web/skins/classic/views/console.php @@ -183,6 +183,7 @@ xhtmlHeaders( __FILE__, translate('Console') ); - ' : '>') . $monitor['Name'] ?>
+ + ' : '>') . $monitor['Name'] ?>
+
+ ', + array_map(function($group_id){ + $Group = new Group($group_id); + return implode(' > ', array_map(function($Group){ return $Group->Name(); }, $Group->Parents())); + }, $Monitor->GroupIds() ) ); +?> + '.translate('Fn'.$monitor['Function']).( empty($monitor['Enabled']) ? ', disabled' : '' ) .'', canEdit( 'Monitors' ) ) ?>
Date: Fri, 2 Mar 2018 17:19:10 -0600 Subject: [PATCH 046/375] url to css/spinner.css should be relative fixes http 404 not found errors for this css file --- web/skins/classic/views/js/log.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/log.js b/web/skins/classic/views/js/log.js index a7a8aa2c6..678cf900d 100644 --- a/web/skins/classic/views/js/log.js +++ b/web/skins/classic/views/js/log.js @@ -286,7 +286,7 @@ sortReverse: true warningPrefix: "", errorPrefix: "" }); - new Asset.css( "/css/spinner.css" ); + new Asset.css( "css/spinner.css" ); fetchNextLogs(); } From a6827c97abadb2910024b3965d1773da97d1dfb1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Mar 2018 18:24:39 -0800 Subject: [PATCH 047/375] Cleanup, add some sanity checks --- src/zm_eventstream.cpp | 55 ++++++++++++++++++++++++++++-------------- src/zm_eventstream.h | 16 ++---------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index 821750216..69c840343 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -88,43 +88,48 @@ bool EventStream::loadInitialEventData( int monitor_id, time_t event_time ) { } bool EventStream::loadInitialEventData( int init_event_id, unsigned int init_frame_id ) { - loadEventData( init_event_id ); + loadEventData(init_event_id); if ( init_frame_id ) { - curr_stream_time = event_data->frames[init_frame_id-1].timestamp; - curr_frame_id = init_frame_id; + if ( init_frame_id >= event_data->frame_count ) { + Error("Invalid frame id specified. %d > %d", init_frame_id, event_data->frame_count ); + curr_stream_time = event_data->start_time; + } else { + curr_stream_time = event_data->frames[init_frame_id-1].timestamp; + curr_frame_id = init_frame_id; + } } else { curr_stream_time = event_data->start_time; } - return( true ); + return true; } -bool EventStream::loadEventData( int event_id ) { +bool EventStream::loadEventData(int event_id) { static char sql[ZM_SQL_MED_BUFSIZ]; - snprintf( sql, sizeof(sql), "SELECT MonitorId, StorageId, Frames, unix_timestamp( StartTime ) AS StartTimestamp, (SELECT max(Delta)-min(Delta) FROM Frames WHERE EventId=Events.Id) AS Duration, DefaultVideo, Scheme FROM Events WHERE Id = %d", event_id ); + snprintf(sql, sizeof(sql), "SELECT MonitorId, StorageId, Frames, unix_timestamp( StartTime ) AS StartTimestamp, (SELECT max(Delta)-min(Delta) FROM Frames WHERE EventId=Events.Id) AS Duration, DefaultVideo, Scheme FROM Events WHERE Id = %d", event_id); - if ( mysql_query( &dbconn, sql ) ) { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + if ( mysql_query(&dbconn, sql) ) { + Error("Can't run query: %s", mysql_error(&dbconn)); + exit(mysql_errno(&dbconn)); } - MYSQL_RES *result = mysql_store_result( &dbconn ); + MYSQL_RES *result = mysql_store_result(&dbconn); if ( !result ) { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + Error("Can't use query result: %s", mysql_error(&dbconn)); + exit(mysql_errno(&dbconn)); } - if ( !mysql_num_rows( result ) ) { - Fatal( "Unable to load event %d, not found in DB", event_id ); + if ( !mysql_num_rows(result) ) { + Fatal("Unable to load event %d, not found in DB", event_id); } - MYSQL_ROW dbrow = mysql_fetch_row( result ); + MYSQL_ROW dbrow = mysql_fetch_row(result); - if ( mysql_errno( &dbconn ) ) { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + if ( mysql_errno(&dbconn) ) { + Error("Can't fetch row: %s", mysql_error(&dbconn)); + exit(mysql_errno(&dbconn)); } delete event_data; @@ -886,3 +891,17 @@ void EventStream::runStream() { closeComms(); } +void EventStream::setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) { + loadInitialEventData( init_event_id, init_frame_id ); + if ( !(monitor = Monitor::Load( event_data->monitor_id, false, Monitor::QUERY )) ) { + Fatal( "Unable to load monitor id %d for streaming", event_data->monitor_id ); + return; + } +} +void EventStream::setStreamStart( int monitor_id, time_t event_time ) { + loadInitialEventData( monitor_id, event_time ); + if ( !(monitor = Monitor::Load( event_data->monitor_id, false, Monitor::QUERY )) ) { + Fatal( "Unable to load monitor id %d for streaming", monitor_id ); + return; + } +} diff --git a/src/zm_eventstream.h b/src/zm_eventstream.h index 02e90f70a..3a9168eac 100644 --- a/src/zm_eventstream.h +++ b/src/zm_eventstream.h @@ -110,20 +110,8 @@ class EventStream : public StreamBase { ffmpeg_input = NULL; } - void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) { - loadInitialEventData( init_event_id, init_frame_id ); - if ( !(monitor = Monitor::Load( event_data->monitor_id, false, Monitor::QUERY )) ) { - Fatal( "Unable to load monitor id %d for streaming", event_data->monitor_id ); - return; - } - } - void setStreamStart( int monitor_id, time_t event_time ) { - loadInitialEventData( monitor_id, event_time ); - if ( !(monitor = Monitor::Load( event_data->monitor_id, false, Monitor::QUERY )) ) { - Fatal( "Unable to load monitor id %d for streaming", monitor_id ); - return; - } - } + void setStreamStart( int init_event_id, unsigned int init_frame_id ); + void setStreamStart( int monitor_id, time_t event_time ); void setStreamMode( StreamMode p_mode ) { mode = p_mode; } From ede13ac41b659837e33be20fbb1b57f38696ce4f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Mar 2018 18:25:20 -0800 Subject: [PATCH 048/375] put all db access after finishing encoding, because we don 't care when they happen, and we need the encoding done. --- src/zm_event.cpp | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 17c385c87..7b5ca2c38 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -227,23 +227,8 @@ Event::Event( } // Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap, bool p_videoEvent ) Event::~Event() { - static char sql[ZM_SQL_MED_BUFSIZ]; - struct DeltaTimeval delta_time; - DELTA_TIMEVAL(delta_time, end_time, start_time, DT_PREC_2); - Debug(2, "start_time:%d.%d end_time%d.%d", start_time.tv_sec, start_time.tv_usec, end_time.tv_sec, end_time.tv_usec ); - if ( frames > last_db_frame ) { - - Debug( 1, "Adding closing frame %d to DB", frames ); - snprintf( sql, sizeof(sql), - "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )", - id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec ); - db_mutex.lock(); - if ( mysql_query( &dbconn, sql ) ) { - Error( "Can't insert frame: %s", mysql_error( &dbconn ) ); - } - db_mutex.unlock(); - } + // We cose the videowriter first, because it might take some time, and we don't want to lock the db if we can avoid it /* Close the video file */ if ( videowriter != NULL ) { @@ -261,10 +246,32 @@ Event::~Event() { } } - snprintf( sql, sizeof(sql), "update Events set Name='%s%d', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo = '%s' where Id = %d", monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, video_name, id ); + + static char sql[ZM_SQL_MED_BUFSIZ]; + struct DeltaTimeval delta_time; + DELTA_TIMEVAL(delta_time, end_time, start_time, DT_PREC_2); + Debug(2, "start_time:%d.%d end_time%d.%d", start_time.tv_sec, start_time.tv_usec, end_time.tv_sec, end_time.tv_usec ); + + if ( frames > last_db_frame ) { + Debug( 1, "Adding closing frame %d to DB", frames ); + snprintf( sql, sizeof(sql), + "INSERT INTO Frames ( EventId, FrameId, TimeStamp, Delta ) VALUES ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )", + id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec ); + db_mutex.lock(); + if ( mysql_query( &dbconn, sql ) ) { + Error( "Can't insert frame: %s", mysql_error( &dbconn ) ); + } else { + Debug(1,"Success writing last frame"); + } + db_mutex.unlock(); + } + + snprintf( sql, sizeof(sql), "UPDATE Events SET Name='%s%d', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo = '%s' where Id = %d", monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, video_name, id ); db_mutex.lock(); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't update event: %s", mysql_error( &dbconn ) ); + } else { + Debug(1,"Success updating event"); } db_mutex.unlock(); } From 77ded1f5beebab71f565cb77c05c89ec18555d02 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Mar 2018 18:25:46 -0800 Subject: [PATCH 049/375] spacing and increase debug --- src/zm_video.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/zm_video.cpp b/src/zm_video.cpp index 369819098..51f529082 100644 --- a/src/zm_video.cpp +++ b/src/zm_video.cpp @@ -211,6 +211,7 @@ int X264MP4Writer::Open() { int X264MP4Writer::Close() { /* Flush all pending frames */ for ( int i = (x264_encoder_delayed_frames(x264enc) + 1); i > 0; i-- ) { +Debug(1,"Encoding delayed frame"); x264encodeloop(true); } @@ -220,6 +221,7 @@ int X264MP4Writer::Close() { /* Close MP4 handle */ MP4Close(mp4h); + Debug(1,"Optimising"); /* Required for proper HTTP streaming */ MP4Optimize((path + ".incomplete").c_str(), path.c_str()); @@ -228,7 +230,7 @@ int X264MP4Writer::Close() { bOpen = false; - Debug(7, "Video closed. Total frames: %d", frame_count); + Debug(1, "Video closed. Total frames: %d", frame_count); return 0; } @@ -413,7 +415,7 @@ void X264MP4Writer::x264encodeloop(bool bFlush) { } if ( frame_size > 0 || bFlush ) { - Debug(8, "x264 Frame: %d PTS: %d DTS: %d Size: %d\n", + Debug(1, "x264 Frame: %d PTS: %d DTS: %d Size: %d\n", frame_count, x264picout.i_pts, x264picout.i_dts, frame_size); /* Handle the previous frame */ @@ -490,7 +492,7 @@ void X264MP4Writer::x264encodeloop(bool bFlush) { } } else if ( frame_size == 0 ) { - Debug(7, "x264 encode returned zero. Delayed frames: %d", + Debug(1, "x264 encode returned zero. Delayed frames: %d", x264_encoder_delayed_frames(x264enc)); } else { Error("x264 encode failed: %d", frame_size); From d980def64fcf7e78f721a8dea563b0057f74b9c9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Mar 2018 18:26:07 -0800 Subject: [PATCH 050/375] spacing, increase debug --- src/zm_ffmpeg_input.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/zm_ffmpeg_input.cpp b/src/zm_ffmpeg_input.cpp index 70dafb76c..c7b60cd7b 100644 --- a/src/zm_ffmpeg_input.cpp +++ b/src/zm_ffmpeg_input.cpp @@ -121,7 +121,7 @@ AVFrame *FFmpeg_Input::get_frame( int stream_id ) { } if ( (stream_id < 0 ) || ( packet.stream_index == stream_id ) ) { - Debug(1,"Packet is for our stream (%d)", packet.stream_index ); + Debug(3,"Packet is for our stream (%d)", packet.stream_index ); AVCodecContext *context = streams[packet.stream_index].context; @@ -169,9 +169,9 @@ AVFrame *FFmpeg_Input::get_frame( int stream_id ) { frameComplete = 1; # else - ret = zm_avcodec_decode_video( context, frame, &frameComplete, &packet ); + ret = zm_avcodec_decode_video(context, frame, &frameComplete, &packet); if ( ret < 0 ) { - av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE ); + av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE); Error( "Unable to decode frame at frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf ); zm_av_packet_unref( &packet ); continue; @@ -179,7 +179,7 @@ AVFrame *FFmpeg_Input::get_frame( int stream_id ) { #endif } // end if it's the right stream - zm_av_packet_unref( &packet ); + zm_av_packet_unref( &packet ); } // end while ! frameComplete return frame; From 91c9714e43ecbe864fc083d93dd57d275e86200c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Mar 2018 18:26:21 -0800 Subject: [PATCH 051/375] cleanup --- src/zm_monitor.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 0828b497a..164376100 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -3112,13 +3112,16 @@ bool Monitor::closeEvent() { event_delete_thread = NULL; } event_delete_thread = new std::thread([](Event *event) { - delete event; + Event * e = event; + event = NULL; + delete e; + e = NULL; }, event ); video_store_data->recording = (struct timeval){0}; - event = 0; - return( true ); + event = NULL; + return true; } - return( false ); + return false; } unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ) { From c53b6ffbb00f8a5cc09c1a8ae2c8cc2f8a1309f6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Mar 2018 18:26:50 -0800 Subject: [PATCH 052/375] rework montagereview to load data faster and leave event and frame data in json objects --- web/skins/classic/views/js/montagereview.js | 169 ++++++++++++------ .../classic/views/js/montagereview.js.php | 119 +++++------- web/skins/classic/views/montagereview.php | 31 ++-- 3 files changed, 172 insertions(+), 147 deletions(-) diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js index 826c814ca..148b0e50b 100644 --- a/web/skins/classic/views/js/montagereview.js +++ b/web/skins/classic/views/js/montagereview.js @@ -38,42 +38,95 @@ function evaluateLoadTimes() { else if (avgFrac >= 0.2) currentDisplayInterval = (currentDisplayInterval * 1.50).toFixed(1); else if (avgFrac >= 0.1) currentDisplayInterval = (currentDisplayInterval * 2.00).toFixed(1); else currentDisplayInterval = (currentDisplayInterval * 2.50).toFixed(1); - currentDisplayInterval = Math.min(Math.max(currentDisplayInterval, 30), 10000); // limit this from about 30fps to .1 fps + // limit this from about 40fps to .1 fps + currentDisplayInterval = Math.min(Math.max(currentDisplayInterval, 40), 10000); imageLoadTimesEvaluated=0; setSpeed(speedIndex); $('fps').innerHTML="Display refresh rate is " + (1000 / currentDisplayInterval).toFixed(1) + " per second, avgFrac=" + avgFrac.toFixed(3) + "."; } // end evaluateLoadTimes() +function getFrame( monId, time ) { + var Frame = null; + for ( var event_id in events ) { + // Search for the event matching this time. Would be more efficient if we had events indexed by monitor + Event = events[event_id]; + if ( Event.MonitorId != monId || Event.StartTimeSecs > time || Event.EndTimeSecs < time ) + continue; + + var duration = Event.EndTimeSecs - Event.StartTimeSecs; + var frame = parseInt((time - Event.StartTimeSecs)/(duration)*Object.keys(Event.FramesById).length)+1; + // Need to get frame by time, not some fun calc that assumes frames have the same mlength. + // Frames are not sorted. + for ( var frame_id in Event.FramesById ) { +if ( 0 ) { + if ( frame == 0 ) { +console.log("Found frame for time " + time ); +console.log(Frame); + Frame = Event.FramesById[frame_id]; + break; + } + frame --; + continue; +} + if ( + Event.FramesById[frame_id].TimeStampSecs == time + || ( + Event.FramesById[frame_id].TimeStampSecs < time + && ( + (!Event.FramesById[frame_id].NextTimeStampSecs) + || + (Event.FramesById[frame_id].NextTimeStampSecs > time) + ) + ) + ) { + Frame = Event.FramesById[frame_id]; + break; + } + } // end foreach frame in the event. + if ( ! Frame ) { +console.log("Difn't find frame for " + time ); + return null; + } + } // end foreach event + return Frame; +} + // time is seconds since epoch function getImageSource( monId, time ) { if ( liveMode == 1 ) { - var new_url = monitorImageObject[monId].src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) )); + var new_url = monitorImageObject[monId].src.replace( + /rand=\d+/i, + 'rand='+Math.floor((Math.random() * 1000000) ) + ); if ( auth_hash ) { // update auth hash new_url = new_url.replace(/auth=[a-z0-9]+/i, 'auth='+auth_hash); } return new_url; } + var Frame = getFrame(monId, time); + if ( Frame ) { + Event = events[Frame.EventId]; - for ( var i=0, eIdlength = eId.length; i < eIdlength; i++ ) { - // Search for the event matching this time. Would be more efficient if we had events indexed by monitor - if ( eMonId[i] == monId && time >= eStartSecs[i] && time <= eEndSecs[i] ) { - var duration = eEndSecs[i]-eStartSecs[i]; - var frame = parseInt((time - eStartSecs[i])/(duration)*eventFrames[i])+1; - var storage = Storage[eStorageId[i]]; - if ( storage.ServerId ) { - var server = Servers[storage.ServerId]; - if ( server ) { -//console.log( server.Hostname + " for event " + eId[i] ); - return location.protocol + '//' + server.Hostname + '/index.php?view=image&eid=' + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height; - } else { - console.log("No server found for " + storage.ServerId ); - } + var storage = Storage[Event.StorageId]; + if ( storage.ServerId ) { + var server = Servers[storage.ServerId]; + if ( server ) { + //console.log( server.Hostname + " for event " + eId[i] ); + return location.protocol + '//' + server.Hostname + + //'/cgi-bin/zms?mode=jpeg&replay=single&event=' + event_id + + //'&frame='+Frame.FrameId + +'/index.php?view=image&eid=' + event_id + '&fid='+Frame.FrameId + + "&width=" + monitorCanvasObj[monId].width + + "&height=" + monitorCanvasObj[monId].height; + } else { + console.log("No server found for " + storage.ServerId ); } - //console.log("No storage found for " + eStorageId[i] ); - return "index.php?view=image&eid=" + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height; } - } // end for + //console.log("No storage found for " + eStorageId[i] ); + return '/index.php?view=image&eid=' + Frame.EventId + '&fid='+Frame.FrameId + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height; + return "/cgi-bin/zms?mode=jpeg&replay=single&event=" + Frame.EventId + '&frame='+Frame.FrameId + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height; + } // end found Frame return "no data"; } @@ -294,7 +347,7 @@ function drawGraph() { canvas.height = cHeight; - if ( eId.length == 0 ) { + if ( Object.keys(events).length == 0 ) { ctx.globalAlpha=1; ctx.font= "40px Georgia"; ctx.fillStyle="white"; @@ -308,24 +361,32 @@ function drawGraph() { // first fill in the bars for the events (not alarms) - for(var i=0; i0); i++) { - // Now put in scored frames (if any) - var x1=parseInt( (fTimeFromSecs[i] - minTimeSecs) / rangeTimeSecs * cWidth) ; // round low end down - var x2=parseInt( (fTimeToSecs[i] - minTimeSecs) / rangeTimeSecs * cWidth + 0.5 ) ; // round up - if(x2-x1 < 2) x2=x1+2; // So it is visible make them all at least this number of seconds wide - ctx.fillStyle=monitorColour[fMonId[i]]; - ctx.globalAlpha = 0.4 + 0.6 * (1 - fScore[i]/maxScore); // Background is scaled but even lowest is twice as dark as the background - ctx.fillRect(x1,monitorIndex[fMonId[i]]*rowHeight,x2-x1,rowHeight); - } + ctx.clearRect(x1,monitorIndex[Event.MonitorId]*rowHeight,x2-x1,rowHeight); // Erase any overlap so it doesn't look artificially darker + ctx.fillRect(x1,monitorIndex[Event.MonitorId]*rowHeight,x2-x1,rowHeight); + + for ( var frame_id in Event.FramesById ) { + var Frame = Event.FramesById[frame_id]; + if ( ! Frame.Score ) + continue; + + // Now put in scored frames (if any) + var x1=parseInt( (Frame.TimeStampSecs - minTimeSecs) / rangeTimeSecs * cWidth) ; // round low end down + var x2=parseInt( (Frame.TimeStampSecs - minTimeSecs) / rangeTimeSecs * cWidth + 0.5 ) ; // round up + if(x2-x1 < 2) x2=x1+2; // So it is visible make them all at least this number of seconds wide + ctx.fillStyle=monitorColour[Event.MonitorId]; + ctx.globalAlpha = 0.4 + 0.6 * (1 - Frame.Score/maxScore); // Background is scaled but even lowest is twice as dark as the background + ctx.fillRect(x1,monitorIndex[Event.MonitorId]*rowHeight,x2-x1,rowHeight); + } // end foreach frame + } // end foreach Event + for(var i=0; i= eStartSecs[i] && currentTimeSecs <= eEndSecs[i] ) { - url="?view=event&eid=" + eId[i] + '&fid=' + parseInt(Math.max(1, Math.min(eventFrames[i], eventFrames[i] * (currentTimeSecs - eStartSecs[i]) / (eEndSecs[i] - eStartSecs[i] + 1) ) )); - break; - } else if ( currentTimeSecs <= eStartSecs[i] ) { - if ( i ) { - // Didn't find an exact event, so go with the one before. - url="?view=event&eid=" + eId[i] + '&fid=' + parseInt(Math.max(1, Math.min(eventFrames[i], eventFrames[i] * (currentTimeSecs - eStartSecs[i]) / (eEndSecs[i] - eStartSecs[i] + 1) ) )); - } - break; - } - } - if ( url ) { - createPopup(url, 'zmEvent', 'event', monitorWidth[monId], monitorHeight[monId]); + var Frame = getFrame( monId, currentTimeSecs ); + if ( Frame ) { + url="?view=event&eid=" + Frame.EventId + '&fid=' +Frame.FrameId; + createPopup(url, 'zmEvent', 'event', monitorWidth[monId], monitorHeight[monId]); } else { url="?view=watch&mid=" + monId.toString(); createPopup(url, 'zmWatch', 'watch', monitorWidth[monId], monitorHeight[monId] ); } - } + } // end if live/events } function zoom(monId,scale) { @@ -787,8 +836,6 @@ function changeDateTime(e) { // >>>>>>>>> Initialization that runs on window load by being at the bottom function initPage() { - canvas = $("timeline"); - ctx = canvas.getContext('2d'); for ( var i = 0, len = monitorPtr.length; i < len; i += 1 ) { var monId = monitorPtr[i]; if ( ! monId ) continue; @@ -804,7 +851,11 @@ function initPage() { loadImage2Monitor( monId, monitorImageURL[monId] ); } } - drawGraph(); + if ( !liveMode ) { + canvas = $("timeline"); + ctx = canvas.getContext('2d'); + drawGraph(); + } setSpeed(speedIndex); //setFit(fitMode); // will redraw //setLive(liveMode); // will redraw diff --git a/web/skins/classic/views/js/montagereview.js.php b/web/skins/classic/views/js/montagereview.js.php index 029eb92ff..1349ee512 100644 --- a/web/skins/classic/views/js/montagereview.js.php +++ b/web/skins/classic/views/js/montagereview.js.php @@ -9,10 +9,14 @@ echo $offset . '; // ' . floor($offset / 3600) . ' hours '; var currentScale=; var liveMode=; var fitMode=; -var currentSpeed=; // slider scale, which is only for replay and relative to real time + +// slider scale, which is only for replay and relative to real time +var currentSpeed=; var speedIndex=; -// will be set based on performance, this is the display interval in milliseconds for history, and fps for live, and dynamically determined (in ms) +// will be set based on performance, this is the display interval in milliseconds +// for history, and fps for live, and dynamically determined (in ms) + var currentDisplayInterval=; var playSecsperInterval=1; // How many seconds of recorded image we play per refresh determined by speed (replay rate) and display interval; (default=1 if coming from live) var timerInterval; // milliseconds between interrupts @@ -21,12 +25,6 @@ var freeTimeLastIntervals=[]; // Percentage of current interval used in loadi var imageLoadTimesEvaluated=0; // running count var imageLoadTimesNeeded=15; // and how many we need var timeLabelsFractOfRow = 0.9; -var eMonId = []; -var eId = []; -var eStorageId = []; -var eStartSecs = []; -var eEndSecs = []; -var eventFrames = []; // this is going to presume all frames equal durationlength fetch( PDO::FETCH_ASSOC ) ) { + $event_id = $event['Id']; + $EventsById[$event_id] = $event; + } - $StartTimeSecs = strtotime($event['StartTime']); - $EndTimeSecs = strtotime($event['EndTime']); + $next_frames = array(); - if ( $minTimeSecs > $StartTimeSecs ) $minTimeSecs = $StartTimeSecs; + if ( $result = dbQuery($frameSql) ) { + $next_frame = null; + while( $frame = $result->fetch(PDO::FETCH_ASSOC) ) { + $event_id = $frame['EventId']; + $event = &$EventsById[$event_id]; + + $frame['TimeStampSecs'] = $event['StartTimeSecs'] + $frame['Delta']; + if ( !isset($event['FramesById']) ) { + $event['FramesById'] = array(); + $frame['NextTimeStampSecs'] = 0; + } else { + $frame['NextTimeStampSecs'] = $next_frames[$frame['EventId']]['TimeStampSecs'];; + } + $event['FramesById'] += array( $frame['Id']=>$frame ); + $next_frames[$frame['EventId']] = $frame; + } + } + + echo "var events = {\n"; + foreach ( $EventsById as $event_id=>$event ) { + + $StartTimeSecs = $event['StartTimeSecs']; + $EndTimeSecs = $event['EndTimeSecs']; + + if ( $minTimeSecs > $StartTimeSecs ) $minTimeSecs = $StartTimeSecs; if ( $maxTimeSecs < $EndTimeSecs ) $maxTimeSecs = $EndTimeSecs; - echo " -eMonId[$index]=" . $event['MonitorId'] . "; -eStorageId[$index]=".$event['StorageId'] . "; -eId[$index]=" . $event['Id'] . "; -eStartSecs[$index]=" . $StartTimeSecs . "; -eEndSecs[$index]=" . $EndTimeSecs . "; -eventFrames[$index]=" . $event['Frames'] . "; - "; + $event_json = json_encode($event, JSON_PRETTY_PRINT); + echo " $event_id : $event_json,\n"; $index = $index + 1; - if ( $event['MaxScore'] > 0 ) + if ( $event['MaxScore'] > 0 ) { + if ( $event['MaxScore'] > $maxScore ) + $maxScore = $event['MaxScore']; $anyAlarms = true; + } } +echo " };\n"; // if there is no data set the min/max to the passed in values if ( $index == 0 ) { @@ -93,60 +118,6 @@ eventFrames[$index]=" . $event['Frames'] . "; $maxTimeSecs = strtotime($maxTime); } - // If we had any alarms in those events, this builds the list of all alarm frames, but consolidated down to (nearly) contiguous segments - // comparison in else governs how aggressively it consolidates - - echo " -var fMonId = []; -var fTimeFromSecs = []; -var fTimeToSecs = []; -var fScore = []; -"; -$maxScore=0; -$index=0; -$mId=-1; -$fromSecs=-1; -$toSecs=-1; -$maxScore=-1; - -if ( $anyAlarms && $result = dbQuery( $frameSql ) ) { - - while( $frame = $result->fetch( PDO::FETCH_ASSOC ) ) { - if ( $mId < 0 ) { - $mId = $frame['MonitorId']; - $fromSecs = $frame['TimeStampSecs']; - $toSecs = $frame['TimeStampSecs']; - $maxScore = $frame['Score']; - } else if ( $mId != $frame['MonitorId'] || $frame['TimeStampSecs'] - $toSecs > 10 ) { - // dump this one start a new - $index++; - echo " - -fMonId[$index]= $mId; -fTimeFromSecs[$index]= $fromSecs; -fTimeToSecs[$index]= $toSecs; -fScore[$index]= $maxScore; -"; - $mId = $frame['MonitorId']; - $fromSecs = $frame['TimeStampSecs']; - $toSecs = $frame['TimeStampSecs']; - $maxScore = $frame['Score']; - } else { - // just add this one on - $toSecs = $frame['TimeStampSecs']; - if ( $maxScore < $frame['Score'] ) $maxScore = $frame['Score']; - } - } -} -if ( $mId > 0 ) { - echo " - fMonId[$index]= $mId; - fTimeFromSecs[$index]= $fromSecs; - fTimeToSecs[$index]= $toSecs; - fScore[$index]= $maxScore; -"; -} - echo "var maxScore=$maxScore;\n"; // used to skip frame load if we find no alarms. } // end if initialmodeislive diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index d2d60b8e7..c5e5e3913 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -94,14 +94,14 @@ if (isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && count($display // if the bulk record has not been written - to be able to include more current frames reduce bulk frame sizes (event size can be large) // Note we round up just a bit on the end time as otherwise you get gaps, like 59.78 to 00 in the next second, which can give blank frames when moved through slowly. -$eventsSql = ' - SELECT E.Id,E.Name,E.StorageId,E.StartTime AS StartTime, - CASE WHEN E.EndTime IS NULL THEN (SELECT NOW()) ELSE E.EndTime END AS EndTime, - E.Length, - CASE WHEN E.Frames IS NULL THEN (SELECT COUNT(*) FROM Frames F WHERE F.EventId=E.Id) ELSE E.Frames END AS Frames, - E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId +$eventsSql = 'SELECT + E.Id,E.Name,E.StorageId, + E.StartTime AS StartTime,UNIX_TIMESTAMP(E.StartTime) AS StartTimeSecs, + CASE WHEN E.EndTime IS NULL THEN (SELECT NOW()) ELSE E.EndTime END AS EndTime, + UNIX_TIMESTAMP(EndTime) AS EndTimeSecs, + E.Length, E.Frames, E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId FROM Events AS E - WHERE NOT isnull(E.Frames) + WHERE 1 > 0 '; // select E.Id,E.Name,UNIX_TIMESTAMP(E.StartTime) as StartTimeSecs,UNIX_TIMESTAMP(max(DATE_ADD(E.StartTime, Interval Delta+0.5 Second))) as CalcEndTimeSecs, E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId @@ -112,10 +112,9 @@ $eventsSql = ' // Note that the delta value seems more accurate than the time stamp for some reason. $frameSql = ' - SELECT E.Id AS eId, E.MonitorId, UNIX_TIMESTAMP(DATE_ADD(E.StartTime, Interval Delta Second)) AS TimeStampSecs, max(F.Score) AS Score - FROM Events AS E - INNER JOIN Frames AS F ON (F.EventId = E.Id) - WHERE F.Score>0 + SELECT Id, FrameId, EventId, TimeStamp, UNIX_TIMESTAMP(TimeStamp) AS TimeStampSecs, Score, Delta + FROM Frames + WHERE EventId IN (SELECT E.Id FROM Events AS E WHERE 1>0 '; // This program only calls itself with the time range involved -- it does all monitors (the user can see, in the called group) all the time @@ -183,7 +182,7 @@ if ( isset($_REQUEST['current']) ) $liveMode = 1; // default to live if ( isset($_REQUEST['live']) && $_REQUEST['live']=='0' ) - $liveMode=0; + $liveMode = 0; $initialDisplayInterval = 1000; if ( isset($_REQUEST['displayinterval']) ) @@ -196,10 +195,14 @@ if ( isset($minTime) && isset($maxTime) ) { $maxTimeSecs = strtotime($maxTime); Logger::Debug("Min/max time secs: $minTimeSecs $maxTimeSecs"); $eventsSql .= " AND EndTime > '" . $minTime . "' AND StartTime < '" . $maxTime . "'"; - $frameSql .= " AND TimeStamp > '" . $minTime . "' AND TimeStamp < '" . $maxTime . "'"; + $frameSql .= " AND EndTime > '" . $minTime . "' AND StartTime < '" . $maxTime . "'"; + $frameSql .= ") AND TimeStamp > '" . $minTime . "' AND TimeStamp < '" . $maxTime . "'"; } -$frameSql .= ' GROUP BY E.Id, E.MonitorId, F.TimeStamp, F.Delta ORDER BY E.MonitorId, F.TimeStamp ASC'; +#$frameSql .= ' GROUP BY E.Id, E.MonitorId, F.TimeStamp, F.Delta ORDER BY E.MonitorId, F.TimeStamp ASC'; +#$frameSql .= ' GROUP BY E.Id, E.MonitorId, F.TimeStamp, F.Delta ORDER BY E.MonitorId, F.TimeStamp ASC'; $eventsSql .= ' ORDER BY E.Id ASC'; +// DESC is intentional. We process them in reverse order so that we can point each frame to the next one in time. +$frameSql .= ' ORDER BY Id DESC'; $monitors = array(); foreach( $displayMonitors as $row ) { From 47ec0abf117b4eb0f69f5fc823b1bcc492a66e67 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Mar 2018 18:27:03 -0800 Subject: [PATCH 053/375] spacing --- src/zms.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zms.cpp b/src/zms.cpp index 66b3dc683..d3947c99e 100644 --- a/src/zms.cpp +++ b/src/zms.cpp @@ -283,10 +283,10 @@ int main( int argc, const char *argv[] ) { stream.setStreamMode( replay ); stream.setStreamQueue( connkey ); if ( monitor_id && event_time ) { - stream.setStreamStart( monitor_id, event_time ); + stream.setStreamStart(monitor_id, event_time); } else { Debug(3, "Setting stream start to frame (%d)", frame_id); - stream.setStreamStart( event_id, frame_id ); + stream.setStreamStart(event_id, frame_id); } if ( mode == ZMS_JPEG ) { stream.setStreamType( EventStream::STREAM_JPEG ); From 3dc157732a6ad1df4021ab1801aa7530f79c44ec Mon Sep 17 00:00:00 2001 From: Mike R Date: Sat, 3 Mar 2018 00:58:35 -0500 Subject: [PATCH 054/375] Issue 1963: Remove spaces from example api calls. --- docs/api.rst | 58 ++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index 36467525a..706748880 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -98,15 +98,15 @@ This command will add a new http monitor. :: - curl -XPOST http://server/zm/api/monitors.json -d "Monitor[Name]=Cliff-Burton \ - &Monitor[Function]=Modect \ - &Monitor[Protocol]=http \ - &Monitor[Method]=simple \ - &Monitor[Host]=usr:pass@192.168.11.20 \ - &Monitor[Port]=80 \ - &Monitor[Path]=/mjpg/video.mjpg \ - &Monitor[Width]=704 \ - &Monitor[Height]=480 \ + curl -XPOST http://server/zm/api/monitors.json -d "Monitor[Name]=Cliff-Burton\ + &Monitor[Function]=Modect\ + &Monitor[Protocol]=http\ + &Monitor[Method]=simple\ + &Monitor[Host]=usr:pass@192.168.11.20\ + &Monitor[Port]=80\ + &Monitor[Path]=/mjpg/video.mjpg\ + &Monitor[Width]=704\ + &Monitor[Height]=480\ &Monitor[Colours]=4" Edit monitor 1 @@ -304,26 +304,26 @@ Create a Zone :: - curl -XPOST http://server/zm/api/zones.json -d "Zone[Name]=Jason-Newsted \ - &Zone[MonitorId]=3 \ - &Zone[Type]=Active \ - &Zone[Units]=Percent \ - &Zone[NumCoords]=4 \ - &Zone[Coords]=0,0 639,0 639,479 0,479 \ - &Zone[AlarmRGB]=16711680 \ - &Zone[CheckMethod]=Blobs \ - &Zone[MinPixelThreshold]=25 \ - &Zone[MaxPixelThreshold]= \ - &Zone[MinAlarmPixels]=9216 \ - &Zone[MaxAlarmPixels]= \ - &Zone[FilterX]=3 \ - &Zone[FilterY]=3 \ - &Zone[MinFilterPixels]=9216 \ - &Zone[MaxFilterPixels]=230400 \ - &Zone[MinBlobPixels]=6144 \ - &Zone[MaxBlobPixels]= \ - &Zone[MinBlobs]=1 \ - &Zone[MaxBlobs]= \ + curl -XPOST http://server/zm/api/zones.json -d "Zone[Name]=Jason-Newsted\ + &Zone[MonitorId]=3\ + &Zone[Type]=Active\ + &Zone[Units]=Percent\ + &Zone[NumCoords]=4\ + &Zone[Coords]=0,0 639,0 639,479 0,479\ + &Zone[AlarmRGB]=16711680\ + &Zone[CheckMethod]=Blobs\ + &Zone[MinPixelThreshold]=25\ + &Zone[MaxPixelThreshold]=\ + &Zone[MinAlarmPixels]=9216\ + &Zone[MaxAlarmPixels]=\ + &Zone[FilterX]=3\ + &Zone[FilterY]=3\ + &Zone[MinFilterPixels]=9216\ + &Zone[MaxFilterPixels]=230400\ + &Zone[MinBlobPixels]=6144\ + &Zone[MaxBlobPixels]=\ + &Zone[MinBlobs]=1\ + &Zone[MaxBlobs]=\ &Zone[OverloadFrames]=0" PTZ Control APIs From 2864876d28c6cde03d84f11359d3ccbb62ac1479 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 3 Mar 2018 09:25:04 -0800 Subject: [PATCH 055/375] fix spacing, add code comment --- web/includes/Control.php | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/web/includes/Control.php b/web/includes/Control.php index 343a7b31a..de5f221ff 100644 --- a/web/includes/Control.php +++ b/web/includes/Control.php @@ -204,6 +204,7 @@ private $defaults = array( $this->{$k} = $v; } } + // Set default values foreach ( $this->defaults as $k=>$v ) { if ( ( ! array_key_exists( $k, $this ) ) or ( $this->{$k} == '' ) ) { $this->{$k} = $v; @@ -212,16 +213,17 @@ private $defaults = array( $fields = array_keys( $this->defaults ); -if ( array_key_exists( 'Id', $this ) ) { - $sql = 'UPDATE Controls SET '.implode(', ', array_map( function($field) {return $field.'=?';}, $fields ) ) . ' WHERE Id=?'; - $values = array_map( function($field){return $this->{$field};}, $fields ); - $values[] = $this->{'Id'}; - dbQuery( $sql, $values ); -} else { - $sql = 'INSERT INTO Controls SET '.implode(', ', array_map( function($field) {return $field.'=?';}, $fields ) ) . ''; - $values = array_map( function($field){return $this->{$field};}, $fields ); - dbQuery( $sql, $values ); -} + if ( array_key_exists( 'Id', $this ) ) { + $sql = 'UPDATE Controls SET '.implode(', ', array_map( function($field) {return $field.'=?';}, $fields ) ) . ' WHERE Id=?'; + $values = array_map( function($field){return $this->{$field};}, $fields ); + $values[] = $this->{'Id'}; + dbQuery( $sql, $values ); + } else { + $sql = 'INSERT INTO Controls SET '.implode(', ', array_map( function($field) {return $field.'=?';}, $fields ) ) . ''; + $values = array_map( function($field){return $this->{$field};}, $fields ); + dbQuery( $sql, $values ); + $this->{'Id'} = dbInsertId(); + } } // end function save } // end class Control From 128c4c73e92395c051096624ec9c39cb50ccc652 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 3 Mar 2018 13:29:39 -0800 Subject: [PATCH 056/375] Add official sql for loading a Monitor --- src/zm_monitor.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/zm_monitor.h b/src/zm_monitor.h index ff6ceca50..d18cd1c13 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -330,6 +330,8 @@ protected: int n_linked_monitors; MonitorLink **linked_monitors; + // This is the official SQL (and ordering of the fields) to load a Monitor. It will be used whereever a Monitor dbrow is needed. WHERE conditions can be appended + std::string load_monitor_sql = "SELECT Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, OutputCodec, Encoder, OutputContainer, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors"; public: explicit Monitor( int p_id ); From db8ab28845e19df1e842d8dacb8e2fa45ef6c2cc Mon Sep 17 00:00:00 2001 From: Steve Gilvarry Date: Sun, 4 Mar 2018 08:37:21 +1100 Subject: [PATCH 057/375] Add return false to window.history.back Adding this makes it work in Safari --- web/skins/classic/views/events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index 96cd704c4..d9ec1daf3 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -119,7 +119,7 @@ if ( $pages > 1 ) { ?>
- +
From 1c740de5dcf60e9e25e6d07e306c697042d7760a Mon Sep 17 00:00:00 2001 From: Steve Gilvarry Date: Sun, 4 Mar 2018 13:37:30 +1100 Subject: [PATCH 058/375] Add Return False to Event Back --- web/skins/classic/views/event.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index ee0c212f3..38118a9f2 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -114,7 +114,7 @@ if ( ! $Event->Id() ) { ">Frames() ?>/AlarmFrames() ?> ">TotScore() ?>/AvgScore() ?>/MaxScore() ?> DiskSpace(null)) . ' on ' . $Event->Storage()->Name() ?> -
+