Merge branch 'master' into update_do_debian_release
|
@ -66,6 +66,24 @@ set(CMAKE_CXX_FLAGS_DEBUG "-Wall -D__STDC_CONSTANT_MACROS -g")
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
||||||
|
|
||||||
|
# GCC below 6.0 doesn't support __target__("fpu=neon") attribute, required for compiling ARM Neon code, otherwise compilation fails.
|
||||||
|
# Must use -mfpu=neon compiler flag instead, but only do that for processors that support neon, otherwise strip the neon code alltogether,
|
||||||
|
# because passing -fmpu=neon is unsafe to processors that don't support neon
|
||||||
|
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" AND CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||||
|
IF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
|
||||||
|
EXEC_PROGRAM(grep ARGS " neon " "/proc/cpuinfo" OUTPUT_VARIABLE neonoutput RETURN_VALUE neonresult)
|
||||||
|
IF(neonresult EQUAL 0)
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mfpu=neon")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mfpu=neon")
|
||||||
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -mfpu=neon")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mfpu=neon")
|
||||||
|
ELSE(neonresult EQUAL 0)
|
||||||
|
add_definitions(-DZM_STRIP_NEON=1)
|
||||||
|
message(STATUS "ARM Neon is not available on this processor. Neon functions will be absent")
|
||||||
|
ENDIF(neonresult EQUAL 0)
|
||||||
|
ENDIF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
|
||||||
|
ENDIF(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" AND CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||||
|
|
||||||
# Modules that we need:
|
# Modules that we need:
|
||||||
include (GNUInstallDirs)
|
include (GNUInstallDirs)
|
||||||
include (CheckIncludeFile)
|
include (CheckIncludeFile)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
--
|
||||||
|
-- This updates a 1.30.2 database to 1.30.3
|
||||||
|
--
|
||||||
|
-- No changes required
|
||||||
|
--
|
|
@ -0,0 +1,5 @@
|
||||||
|
--
|
||||||
|
-- This updates a 1.30.3 database to 1.30.4
|
||||||
|
--
|
||||||
|
-- No changes required
|
||||||
|
--
|
|
@ -157,7 +157,9 @@ Upgrades
|
||||||
|
|
||||||
sudo zmupdate.pl --user=root --pass=<mysql_root_pwd> --version=<from version>
|
sudo zmupdate.pl --user=root --pass=<mysql_root_pwd> --version=<from version>
|
||||||
|
|
||||||
5. Now start zoneminder:
|
5. Now restart nginx and php-fpm then start and zoneminder:
|
||||||
|
|
||||||
|
sudo systemctl restart nginx
|
||||||
|
sudo systemctl restart php-fpm
|
||||||
sudo systemctl start zoneminder
|
sudo systemctl start zoneminder
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
# This will tell zoneminder's cmake process we are building against a known distro
|
# This will tell zoneminder's cmake process we are building against a known distro
|
||||||
%global zmtargetdistro %{?rhel:el%{rhel}}%{!?rhel:fc%{fedora}}
|
%global zmtargetdistro %{?rhel:el%{rhel}}%{!?rhel:fc%{fedora}}
|
||||||
|
|
||||||
|
# Fedora >= 25 needs apcu backwards compatibility module
|
||||||
|
%if 0%{?fedora} >= 25
|
||||||
|
%global with_apcu_bc 1
|
||||||
|
%endif
|
||||||
|
|
||||||
# Include files for SysV init or systemd
|
# Include files for SysV init or systemd
|
||||||
%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7
|
%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7
|
||||||
%global with_init_systemd 1
|
%global with_init_systemd 1
|
||||||
|
@ -28,8 +33,8 @@
|
||||||
%global _hardened_build 1
|
%global _hardened_build 1
|
||||||
|
|
||||||
Name: zoneminder
|
Name: zoneminder
|
||||||
Version: 1.30.2
|
Version: 1.30.4
|
||||||
Release: 2%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: A camera monitoring and analysis tool
|
Summary: A camera monitoring and analysis tool
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
# jscalendar is LGPL (any version): http://www.dynarch.com/projects/calendar/
|
# jscalendar is LGPL (any version): http://www.dynarch.com/projects/calendar/
|
||||||
|
@ -86,8 +91,8 @@ BuildRequires: polkit-devel
|
||||||
Requires: php-mysqli
|
Requires: php-mysqli
|
||||||
Requires: php-common
|
Requires: php-common
|
||||||
Requires: php-gd
|
Requires: php-gd
|
||||||
%{?fedora:Requires: php-pecl-apcu-bc}
|
Requires: php-pecl-apcu
|
||||||
%{?rhel:Requires: php-pecl-apcu}
|
%{?with_apcu_bc:Requires: php-pecl-apcu-bc}
|
||||||
Requires: cambozola
|
Requires: cambozola
|
||||||
Requires: net-tools
|
Requires: net-tools
|
||||||
Requires: psmisc
|
Requires: psmisc
|
||||||
|
@ -132,8 +137,7 @@ designed to support as many cameras as you can attach to your computer without
|
||||||
too much degradation of performance.
|
too much degradation of performance.
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%autosetup -n ZoneMinder-%{version}
|
%autosetup -p 1 -a 1 -n ZoneMinder-%{version}
|
||||||
%autosetup -a 1 -n ZoneMinder-%{version}
|
|
||||||
%{__rm} -rf ./web/api/app/Plugin/Crud
|
%{__rm} -rf ./web/api/app/Plugin/Crud
|
||||||
%{__mv} -f crud-%{crud_version} ./web/api/app/Plugin/Crud
|
%{__mv} -f crud-%{crud_version} ./web/api/app/Plugin/Crud
|
||||||
|
|
||||||
|
@ -338,6 +342,14 @@ rm -rf %{_docdir}/%{name}-%{version}
|
||||||
%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/run/zoneminder
|
%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/run/zoneminder
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Tue May 09 2017 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.4-1
|
||||||
|
- modify autosetup macro parameters
|
||||||
|
- modify requirements for php-pecl-acpu-bc package
|
||||||
|
- 1.30.4 release
|
||||||
|
|
||||||
|
* Tue May 02 2017 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.3-1
|
||||||
|
- 1.30.3 release
|
||||||
|
|
||||||
* Thu Mar 30 2017 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.2-2
|
* Thu Mar 30 2017 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.30.2-2
|
||||||
- 1.30.2 release
|
- 1.30.2 release
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
||||||
,libdata-uuid-perl
|
,libdata-uuid-perl
|
||||||
,mysql-client | virtual-mysql-client
|
,mysql-client | virtual-mysql-client
|
||||||
,perl-modules
|
,perl-modules
|
||||||
,php5-mysql, php5-gd
|
,php5-mysql, php5-gd, php5-apcu, php-apc
|
||||||
,policykit-1
|
,policykit-1
|
||||||
,rsyslog | system-log-daemon
|
,rsyslog | system-log-daemon
|
||||||
,zip
|
,zip
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
d /var/run/zm 0755 www-data www-data
|
d /var/run/zm 0755 www-data www-data
|
||||||
d /tmp/zm 0755 www-data www-data
|
d /tmp/zm 0755 www-data www-data
|
||||||
|
d /var/tmp/zm 0755 www-data www-data
|
||||||
|
|
|
@ -63,7 +63,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
||||||
,libdata-uuid-perl
|
,libdata-uuid-perl
|
||||||
,mysql-client | virtual-mysql-client
|
,mysql-client | virtual-mysql-client
|
||||||
,perl-modules
|
,perl-modules
|
||||||
,php5-mysql | php-mysql, php5-gd | php-gd
|
,php5-mysql | php-mysql, php5-gd | php-gd, php-apcu, php-apcu-bc
|
||||||
,policykit-1
|
,policykit-1
|
||||||
,rsyslog | system-log-daemon
|
,rsyslog | system-log-daemon
|
||||||
,zip
|
,zip
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
#!/usr/bin/make -f
|
|
||||||
# -*- makefile -*-
|
|
||||||
|
|
||||||
# Uncomment this to turn on verbose mode.
|
|
||||||
#export DH_VERBOSE=1
|
|
||||||
|
|
||||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
|
||||||
export DEB_LDFLAGS_MAINT_APPEND += -Wl,--as-needed
|
|
||||||
|
|
||||||
ifeq ($(DEB_BUILD_ARCH_OS),hurd)
|
|
||||||
ARGS:= -DZM_NO_MMAP=ON
|
|
||||||
endif
|
|
||||||
|
|
||||||
%:
|
|
||||||
dh $@ --parallel --buildsystem=cmake --builddirectory=dbuild \
|
|
||||||
--with systemd,sphinxdoc,apache2,linktree
|
|
||||||
|
|
||||||
override_dh_auto_configure:
|
|
||||||
dh_auto_configure -- $(ARGS) \
|
|
||||||
-DCMAKE_VERBOSE_MAKEFILE=ON \
|
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
|
||||||
-DZM_CONFIG_DIR="/etc/zm" \
|
|
||||||
-DZM_RUNDIR="/var/run/zm" \
|
|
||||||
-DZM_SOCKDIR="/var/run/zm" \
|
|
||||||
-DZM_TMPDIR="/tmp/zm" \
|
|
||||||
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
|
|
||||||
-DZM_CONTENTDIR="/var/cache/zoneminder"
|
|
||||||
|
|
||||||
override_dh_clean:
|
|
||||||
dh_clean $(MANPAGES1)
|
|
||||||
$(RM) -r docs/_build docs/installationguide
|
|
||||||
|
|
||||||
build-indep:
|
|
||||||
#$(MAKE) -C docs text
|
|
||||||
$(MAKE) -C docs html
|
|
||||||
|
|
||||||
MANPAGES1 = dbuild/scripts/zmupdate.pl.1
|
|
||||||
$(MANPAGES1):
|
|
||||||
# generate man page(s):
|
|
||||||
pod2man -s1 --stderr --utf8 $(patsubst %.1, %, $@) $@
|
|
||||||
|
|
||||||
## reproducible build:
|
|
||||||
LAST_CHANGE=$(shell dpkg-parsechangelog -S Date)
|
|
||||||
BUILD_DATE=$(shell LC_ALL=C date -u "+%B %d, %Y" -d "$(LAST_CHANGE)")
|
|
||||||
override_dh_installman: $(MANPAGES1)
|
|
||||||
$(MAKE) -C docs man SPHINXOPTS="-D today=\"$(BUILD_DATE)\""
|
|
||||||
dh_installman --language=C $(MANPAGES1)
|
|
||||||
|
|
||||||
override_dh_auto_install:
|
|
||||||
dh_auto_install --destdir=$(CURDIR)/debian/tmp
|
|
||||||
# remove worthless files:
|
|
||||||
$(RM) -v $(CURDIR)/debian/tmp/usr/share/perl5/*/*/*/.packlist
|
|
||||||
$(RM) -v $(CURDIR)/debian/tmp/usr/share/perl5/*/*.in
|
|
||||||
# remove empty directories:
|
|
||||||
find $(CURDIR)/debian/tmp/usr -type d -empty -delete -printf 'removed %p\n'
|
|
||||||
# remove extra-license-file:
|
|
||||||
$(RM) -v $(CURDIR)/debian/tmp/usr/share/zoneminder/www/api/lib/Cake/LICENSE.txt
|
|
||||||
|
|
||||||
override_dh_fixperms:
|
|
||||||
dh_fixperms
|
|
||||||
#
|
|
||||||
# As requested by the Debian Webapps Policy Manual §3.2.1
|
|
||||||
chown root:www-data $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
|
||||||
chmod 640 $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
|
||||||
|
|
||||||
override_dh_installinit:
|
|
||||||
dh_installinit --no-start
|
|
||||||
|
|
||||||
override_dh_systemd_start:
|
|
||||||
dh_systemd_start --no-start
|
|
||||||
|
|
||||||
override_dh_systemd_enable:
|
|
||||||
dh_systemd_enable --no-enable
|
|
||||||
|
|
||||||
override_dh_apache2:
|
|
||||||
dh_apache2 --noenable
|
|
||||||
|
|
||||||
override_dh_strip:
|
|
||||||
[ -d "$(CURDIR)/debian/zoneminder-dbg" ] \
|
|
||||||
&& dh_strip --dbg-package=zoneminder-dbg \
|
|
||||||
|| dh_strip
|
|
||||||
|
|
||||||
#%:
|
|
||||||
# dh $@ --parallel --buildsystem=autoconf --with autoreconf
|
|
||||||
#
|
|
||||||
#override_dh_auto_configure:
|
|
||||||
# dh_auto_configure -- \
|
|
||||||
# --sysconfdir=/etc/zm \
|
|
||||||
# --with-mysql=/usr \
|
|
||||||
# --with-webdir=/usr/share/zoneminder \
|
|
||||||
# --with-ffmpeg=/usr \
|
|
||||||
# --with-cgidir=/usr/lib/cgi-bin \
|
|
||||||
# --with-webuser=www-data \
|
|
||||||
# --with-webgroup=www-data \
|
|
||||||
# --enable-mmap=yes
|
|
|
@ -1,28 +0,0 @@
|
||||||
--- distros/ubuntu1604/rules
|
|
||||||
+++ distros/ubuntu1604/rules
|
|
||||||
@@ -58,8 +58,10 @@ override_dh_auto_install:
|
|
||||||
|
|
||||||
override_dh_fixperms:
|
|
||||||
dh_fixperms
|
|
||||||
- ## 637685
|
|
||||||
- chmod -c o-r $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
|
||||||
+ #
|
|
||||||
+ # As requested by the Debian Webapps Policy Manual §3.2.1
|
|
||||||
+ chown root:www-data debian/zoneminder-core/etc/zm/zm.conf
|
|
||||||
+ chmod 640 debian/zoneminder-core/etc/zm/zm.conf
|
|
||||||
|
|
||||||
override_dh_installinit:
|
|
||||||
dh_installinit --no-start
|
|
||||||
--- distros/ubuntu1604/rules
|
|
||||||
+++ distros/ubuntu1604/rules
|
|
||||||
@@ -60,8 +60,8 @@ override_dh_fixperms:
|
|
||||||
dh_fixperms
|
|
||||||
#
|
|
||||||
# As requested by the Debian Webapps Policy Manual §3.2.1
|
|
||||||
- chown root:www-data debian/zoneminder-core/etc/zm/zm.conf
|
|
||||||
- chmod 640 debian/zoneminder-core/etc/zm/zm.conf
|
|
||||||
+ chown root:www-data $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
|
||||||
+ chmod 640 $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
|
||||||
|
|
||||||
override_dh_installinit:
|
|
||||||
dh_installinit --no-start
|
|
|
@ -1,6 +1,3 @@
|
||||||
d /var/run/zm 0755 www-data www-data
|
d /var/run/zm 0755 www-data www-data
|
||||||
d /tmp/zm 0755 www-data www-data
|
d /tmp/zm 0755 www-data www-data
|
||||||
d /var/tmp/zm 0755 www-data www-data
|
d /var/tmp/zm 0755 www-data www-data
|
||||||
d /var/tmp/cache 0755 www-data www-data
|
|
||||||
d /var/tmp/cache/models 0755 www-data www-data
|
|
||||||
d /var/tmp/cache/persistent 0755 www-data www-data
|
|
||||||
|
|
|
@ -309,7 +309,7 @@ The main causes are.
|
||||||
* Capture frame rates. Unless there's a compelling reason in your case there is often little benefit in running cameras at 25fps when 5-10fps would often get you results just as good. Try changing your monitor settings to limit your cameras to lower frame rates. You can still configure ZM to ignore these limits and capture as fast as possible when motion is detected.
|
* Capture frame rates. Unless there's a compelling reason in your case there is often little benefit in running cameras at 25fps when 5-10fps would often get you results just as good. Try changing your monitor settings to limit your cameras to lower frame rates. You can still configure ZM to ignore these limits and capture as fast as possible when motion is detected.
|
||||||
* Run function. Obviously running in Record or Mocord modes or in Modect with lots of events generates a lot of DB and file activity and so CPU and load will increase.
|
* Run function. Obviously running in Record or Mocord modes or in Modect with lots of events generates a lot of DB and file activity and so CPU and load will increase.
|
||||||
* Basic default detection zones. By default when a camera is added one detection zone is added which covers the whole image with a default set of parameters. If your camera covers a view in which various regions are unlikely to generate a valid alarm (ie the sky) then I would experiment with reducing the zone sizes or adding inactive zones to blank out areas you don't want to monitor. Additionally the actual settings of the zone themselves may not be optimal. When doing motion detection the number of changed pixels above a threshold is examined, then this is filter, then contiguous regions are calculated to see if an alarm is generated. If any maximum or minimum threshold is exceeded according to your zone settings at any time the calculation stops. If your settings always result in the calculations going through to the last stage before being failed then additional CPU time is used unnecessarily. Make sure your maximum and minimumzone thresholds are set to sensible values and experiment by switching RECORD_EVENT_STATS on and seeing what the actual values of alarmed pixels etc are during sample events.
|
* Basic default detection zones. By default when a camera is added one detection zone is added which covers the whole image with a default set of parameters. If your camera covers a view in which various regions are unlikely to generate a valid alarm (ie the sky) then I would experiment with reducing the zone sizes or adding inactive zones to blank out areas you don't want to monitor. Additionally the actual settings of the zone themselves may not be optimal. When doing motion detection the number of changed pixels above a threshold is examined, then this is filter, then contiguous regions are calculated to see if an alarm is generated. If any maximum or minimum threshold is exceeded according to your zone settings at any time the calculation stops. If your settings always result in the calculations going through to the last stage before being failed then additional CPU time is used unnecessarily. Make sure your maximum and minimumzone thresholds are set to sensible values and experiment by switching RECORD_EVENT_STATS on and seeing what the actual values of alarmed pixels etc are during sample events.
|
||||||
* Optimise your settings. After you've got some settings you're happy with then switching off RECORD_EVENT_STATS will prevent the statistics being written to the database which saves some time. Other settings which might make a difference are ZM_FAST_RGB_DIFFS, ZM_OPT_FRAME_SERVER and the JPEG_xxx_QUALITY ones.
|
* Optimise your settings. After you've got some settings you're happy with then switching off RECORD_EVENT_STATS will prevent the statistics being written to the database which saves some time. Other settings which might make a difference are ZM_FAST_RGB_DIFFS and the JPEG_xxx_QUALITY ones.
|
||||||
|
|
||||||
I'm sure there are other things which might make a difference such as what else you have running on the box and memory sizes (make sure there's no swapping going on). Also speed of disk etc will make some difference during event capture and also if you are watching the whole time then you may have a bunch of zms processes running also.
|
I'm sure there are other things which might make a difference such as what else you have running on the box and memory sizes (make sure there's no swapping going on). Also speed of disk etc will make some difference during event capture and also if you are watching the whole time then you may have a bunch of zms processes running also.
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,6 @@ Note that these commands are just an example and might not be secure enough for
|
||||||
|
|
||||||
7. If you have chosen to change the ZoneMinder database account credentials to something other than zmuser/zmpass, you must now update zm.conf on each ZoneMinder Server. Change ZM_DB_USER and ZM_DB_PASS to the values you created in the previous step.
|
7. If you have chosen to change the ZoneMinder database account credentials to something other than zmuser/zmpass, you must now update zm.conf on each ZoneMinder Server. Change ZM_DB_USER and ZM_DB_PASS to the values you created in the previous step.
|
||||||
|
|
||||||
Additionally, you must also edit /usr/share/zoneminder/www/api/app/Config/database.php in a similar manner on each ZoneMinder Server. Scroll down and change login and password to the values you created in the previous step.
|
|
||||||
|
|
||||||
8. All ZoneMinders Servers must share a common events folder. This can be done in any manner supported by the underlying operating system. From the Storage Server, share/export a folder to be used for ZoneMinder events.
|
8. All ZoneMinders Servers must share a common events folder. This can be done in any manner supported by the underlying operating system. From the Storage Server, share/export a folder to be used for ZoneMinder events.
|
||||||
|
|
||||||
9. From each ZoneMinder Server, mount the shared events folder on the Storage Server to the events folder on the local ZoneMinder Server.
|
9. From each ZoneMinder Server, mount the shared events folder on the Storage Server to the events folder on the local ZoneMinder Server.
|
||||||
|
|
|
@ -182,7 +182,7 @@ The tarball from the previsouly installed SRPM should be there. This is the name
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
git archive --prefix=ZoneMinder-1.28.1/ -o ~/rpmbuld/SOURCES/zoneminder-1.28.1.tar.gz HEAD
|
git archive --prefix=ZoneMinder-1.28.1/ -o ~/rpmbuild/SOURCES/zoneminder-1.28.1.tar.gz HEAD
|
||||||
|
|
||||||
Note that we are overwriting the original tarball. If you wish to keep the original tarball then create a copy prior to creating the new tarball.
|
Note that we are overwriting the original tarball. If you wish to keep the original tarball then create a copy prior to creating the new tarball.
|
||||||
|
|
||||||
|
|
|
@ -358,24 +358,6 @@ Changed Default DB User
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
If you have changed your DB login/password from zmuser/zmpass, you need to
|
If you have changed your DB login/password from zmuser/zmpass, you need to
|
||||||
update these values in zm.conf and the API's database.php file.
|
update these values in zm.conf.
|
||||||
|
|
||||||
1. Edit zm.conf to change ZM_DB_USER and ZM_DB_PASS to the values you used.
|
1. Edit zm.conf to change ZM_DB_USER and ZM_DB_PASS to the values you used.
|
||||||
|
|
||||||
2. Edit databse.php which can be found in the web server folder zoneminder/www/api/app/Config
|
|
||||||
|
|
||||||
There is a class there called DATABASE_CONFIG -
|
|
||||||
change the $default array to reflect your new details. Example:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
public $default = array(
|
|
||||||
'datasource' => 'Database/Mysql',
|
|
||||||
'persistent' => false,
|
|
||||||
'host' => 'localhost',
|
|
||||||
'login' => 'mynewDBusername',
|
|
||||||
'password' => 'mynewDBpassword'
|
|
||||||
'database' => 'zm',
|
|
||||||
'prefix' => '',
|
|
||||||
//'encoding' => 'utf8',
|
|
||||||
);
|
|
||||||
|
|
|
@ -33,10 +33,6 @@ RUN_AUDIT - The zmaudit daemon exists to check that the saved information in the
|
||||||
|
|
||||||
AUDIT_CHECK_INTERVAL - The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. The default check interval of 900 seconds (15 minutes) is fine for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to make this interval much larger to reduce the impact on your system. This option determines how often these checks are performed.
|
AUDIT_CHECK_INTERVAL - The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. The default check interval of 900 seconds (15 minutes) is fine for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to make this interval much larger to reduce the impact on your system. This option determines how often these checks are performed.
|
||||||
|
|
||||||
OPT_FRAME_SERVER - In some circumstances it is possible for a slow disk to take so long writing images to disk that it causes the analysis daemon to fall behind especially during high frame rate events. Setting this option to yes enables a frame server daemon (zmf) which will be sent the images from the analysis daemon and will do the actual writing of images itself freeing up the analysis daemon to get on with other things. Should this transmission fail or other permanent or transient error occur, this function will fall back to the analysis daemon.
|
|
||||||
|
|
||||||
FRAME_SOCKET_SIZE - For large captured images it is possible for the writes from the analysis daemon to the frame server to fail as the amount to be written exceeds the default buffer size. While the images are then written by the analysis daemon so no data is lost, it defeats the object of the frame server daemon in the first place. You can use this option to indicate that a larger buffer size should be used. Note that you may have to change the existing maximum socket buffer size on your system via sysctl (or in /proc/sys/net/core/wmem_max) to allow this new size to be set. Alternatively you can change the default buffer size on your system in the same way in which case that will be used with no change necessary in this option
|
|
||||||
|
|
||||||
OPT_CONTROL - ZoneMinder includes limited support for controllable cameras. A number of sample protocols are included and others can easily be added. If you wish to control your cameras via ZoneMinder then select this option otherwise if you only have static cameras or use other control methods then leave this option off.
|
OPT_CONTROL - ZoneMinder includes limited support for controllable cameras. A number of sample protocols are included and others can easily be added. If you wish to control your cameras via ZoneMinder then select this option otherwise if you only have static cameras or use other control methods then leave this option off.
|
||||||
|
|
||||||
OPT_TRIGGERS - ZoneMinder can interact with external systems which prompt or cancel alarms. This is done via the zmtrigger.pl script. This option indicates whether you want to use these external triggers. Most people will say no here.
|
OPT_TRIGGERS - ZoneMinder can interact with external systems which prompt or cancel alarms. This is done via the zmtrigger.pl script. This option indicates whether you want to use these external triggers. Most people will say no here.
|
||||||
|
|
|
@ -2716,47 +2716,6 @@ our @options = (
|
||||||
type => $types{boolean},
|
type => $types{boolean},
|
||||||
category => "config",
|
category => "config",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name => "ZM_OPT_FRAME_SERVER",
|
|
||||||
default => "no",
|
|
||||||
description => "Should analysis farm out the writing of images to disk",
|
|
||||||
#requires => [ { name => "ZM_OPT_ADAPTIVE_SKIP", value => "yes" } ],
|
|
||||||
help => qqq("
|
|
||||||
In some circumstances it is possible for a slow disk to take so
|
|
||||||
long writing images to disk that it causes the analysis daemon
|
|
||||||
to fall behind especially during high frame rate events.
|
|
||||||
Setting this option to yes enables a frame server daemon (zmf)
|
|
||||||
which will be sent the images from the analysis daemon and will
|
|
||||||
do the actual writing of images itself freeing up the analysis
|
|
||||||
daemon to get on with other things. Should this transmission
|
|
||||||
fail or other permanent or transient error occur, this function
|
|
||||||
will fall back to the analysis daemon.
|
|
||||||
"),
|
|
||||||
type => $types{boolean},
|
|
||||||
category => "system",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name => "ZM_FRAME_SOCKET_SIZE",
|
|
||||||
default => "0",
|
|
||||||
description => "Specify the frame server socket buffer size if non-standard",
|
|
||||||
requires => [ { name => "ZM_OPT_FRAME_SERVER", value => "yes" } ],
|
|
||||||
help => qqq("
|
|
||||||
For large captured images it is possible for the writes from
|
|
||||||
the analysis daemon to the frame server to fail as the amount
|
|
||||||
to be written exceeds the default buffer size. While the images
|
|
||||||
are then written by the analysis daemon so no data is lost, it
|
|
||||||
defeats the object of the frame server daemon in the first
|
|
||||||
place. You can use this option to indicate that a larger buffer
|
|
||||||
size should be used. Note that you may have to change the
|
|
||||||
existing maximum socket buffer size on your system via sysctl
|
|
||||||
(or in /proc/sys/net/core/wmem_max) to allow this new size to
|
|
||||||
be set. Alternatively you can change the default buffer size on
|
|
||||||
your system in the same way in which case that will be used
|
|
||||||
with no change necessary in this option
|
|
||||||
"),
|
|
||||||
type => $types{integer},
|
|
||||||
category => "system",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name => "ZM_OPT_CONTROL",
|
name => "ZM_OPT_CONTROL",
|
||||||
default => "no",
|
default => "no",
|
||||||
|
|
|
@ -89,7 +89,6 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
|
||||||
my @daemons = (
|
my @daemons = (
|
||||||
'zmc',
|
'zmc',
|
||||||
'zma',
|
'zma',
|
||||||
'zmf',
|
|
||||||
'zmfilter.pl',
|
'zmfilter.pl',
|
||||||
'zmaudit.pl',
|
'zmaudit.pl',
|
||||||
'zmtrigger.pl',
|
'zmtrigger.pl',
|
||||||
|
|
|
@ -251,10 +251,6 @@ if ( $command =~ /^(?:start|restart)$/ )
|
||||||
}
|
}
|
||||||
if ( $monitor->{Function} ne 'Monitor' )
|
if ( $monitor->{Function} ne 'Monitor' )
|
||||||
{
|
{
|
||||||
if ( $Config{ZM_OPT_FRAME_SERVER} )
|
|
||||||
{
|
|
||||||
runCommand( "zmdc.pl start zmf -m $monitor->{Id}" );
|
|
||||||
}
|
|
||||||
runCommand( "zmdc.pl start zma -m $monitor->{Id}" );
|
runCommand( "zmdc.pl start zma -m $monitor->{Id}" );
|
||||||
}
|
}
|
||||||
if ( $Config{ZM_OPT_CONTROL} )
|
if ( $Config{ZM_OPT_CONTROL} )
|
||||||
|
|
|
@ -12,21 +12,19 @@ add_library(zm STATIC ${ZM_BIN_SRC_FILES})
|
||||||
add_executable(zmc zmc.cpp)
|
add_executable(zmc zmc.cpp)
|
||||||
add_executable(zma zma.cpp)
|
add_executable(zma zma.cpp)
|
||||||
add_executable(zmu zmu.cpp)
|
add_executable(zmu zmu.cpp)
|
||||||
add_executable(zmf zmf.cpp)
|
|
||||||
add_executable(zms zms.cpp)
|
add_executable(zms zms.cpp)
|
||||||
|
|
||||||
target_link_libraries(zmc zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
target_link_libraries(zmc zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||||
target_link_libraries(zma zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
target_link_libraries(zma zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||||
target_link_libraries(zmu zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
target_link_libraries(zmu zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||||
target_link_libraries(zmf zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
|
||||||
target_link_libraries(zms zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
target_link_libraries(zms zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||||
|
|
||||||
# Generate man files for the binaries destined for the bin folder
|
# Generate man files for the binaries destined for the bin folder
|
||||||
FOREACH(CBINARY zma zmc zmf zmu)
|
FOREACH(CBINARY zma zmc zmu)
|
||||||
POD2MAN(${CMAKE_CURRENT_SOURCE_DIR}/${CBINARY}.cpp zoneminder-${CBINARY} 8)
|
POD2MAN(${CMAKE_CURRENT_SOURCE_DIR}/${CBINARY}.cpp zoneminder-${CBINARY} 8)
|
||||||
ENDFOREACH(CBINARY zma zmc zmf zmu)
|
ENDFOREACH(CBINARY zma zmc zmu)
|
||||||
|
|
||||||
install(TARGETS zmc zma zmu zmf RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
install(TARGETS zmc zma zmu RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||||
install(TARGETS zms RUNTIME DESTINATION "${ZM_CGIDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
install(TARGETS zms RUNTIME DESTINATION "${ZM_CGIDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||||
install(CODE "execute_process(COMMAND ln -sf zms nph-zms WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})" )
|
install(CODE "execute_process(COMMAND ln -sf zms nph-zms WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})" )
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/nph-zms DESTINATION "${ZM_CGIDIR}")
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/nph-zms DESTINATION "${ZM_CGIDIR}")
|
||||||
|
|
|
@ -39,10 +39,10 @@ Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_co
|
||||||
Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",id,width,height,colours,subpixelorder,capture);
|
Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",id,width,height,colours,subpixelorder,capture);
|
||||||
|
|
||||||
/* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */
|
/* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */
|
||||||
if((colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB32) && (imagesize % 16) != 0) {
|
if((colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB32) && (imagesize % 64) != 0) {
|
||||||
Fatal("Image size is not multiples of 16");
|
Fatal("Image size is not multiples of 64");
|
||||||
} else if(colours == ZM_COLOUR_RGB24 && ((imagesize % 16) != 0 || (imagesize % 12) != 0)) {
|
} else if(colours == ZM_COLOUR_RGB24 && ((imagesize % 64) != 0 || (imagesize % 12) != 0)) {
|
||||||
Fatal("Image size is not multiples of 12 and 16");
|
Fatal("Image size is not multiples of 12 and 64");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
139
src/zm_event.cpp
|
@ -42,8 +42,6 @@ extern "C"
|
||||||
#include "zm_sendfile.h"
|
#include "zm_sendfile.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "zmf.h"
|
|
||||||
|
|
||||||
#if HAVE_SYS_SENDFILE_H
|
#if HAVE_SYS_SENDFILE_H
|
||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -221,135 +219,6 @@ void Event::createNotes( std::string ¬es )
|
||||||
|
|
||||||
int Event::sd = -1;
|
int Event::sd = -1;
|
||||||
|
|
||||||
bool Event::OpenFrameSocket( int monitor_id )
|
|
||||||
{
|
|
||||||
if ( sd > 0 )
|
|
||||||
{
|
|
||||||
close( sd );
|
|
||||||
}
|
|
||||||
|
|
||||||
sd = socket( AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if ( sd < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't create socket: %s", strerror(errno) );
|
|
||||||
return( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
int socket_buffer_size = config.frame_socket_size;
|
|
||||||
if ( socket_buffer_size > 0 )
|
|
||||||
{
|
|
||||||
if ( setsockopt( sd, SOL_SOCKET, SO_SNDBUF, &socket_buffer_size, sizeof(socket_buffer_size) ) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't get socket buffer size to %d, error = %s", socket_buffer_size, strerror(errno) );
|
|
||||||
close( sd );
|
|
||||||
sd = -1;
|
|
||||||
return( false );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int flags;
|
|
||||||
if ( (flags = fcntl( sd, F_GETFL )) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't get socket flags, error = %s", strerror(errno) );
|
|
||||||
close( sd );
|
|
||||||
sd = -1;
|
|
||||||
return( false );
|
|
||||||
}
|
|
||||||
flags |= O_NONBLOCK;
|
|
||||||
if ( fcntl( sd, F_SETFL, flags ) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't set socket flags, error = %s", strerror(errno) );
|
|
||||||
close( sd );
|
|
||||||
sd = -1;
|
|
||||||
return( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
char sock_path[PATH_MAX] = "";
|
|
||||||
snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id );
|
|
||||||
|
|
||||||
struct sockaddr_un addr;
|
|
||||||
|
|
||||||
strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) );
|
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
|
|
||||||
if ( connect( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)+1) < 0 )
|
|
||||||
{
|
|
||||||
Warning( "Can't connect to frame server: %s", strerror(errno) );
|
|
||||||
close( sd );
|
|
||||||
sd = -1;
|
|
||||||
return( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( 1, "Opened connection to frame server" );
|
|
||||||
return( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Event::ValidateFrameSocket( int monitor_id )
|
|
||||||
{
|
|
||||||
if ( sd < 0 )
|
|
||||||
{
|
|
||||||
return( OpenFrameSocket( monitor_id ) );
|
|
||||||
}
|
|
||||||
return( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Event::SendFrameImage( const Image *image, bool alarm_frame )
|
|
||||||
{
|
|
||||||
if ( !ValidateFrameSocket( monitor->Id() ) )
|
|
||||||
{
|
|
||||||
return( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int jpg_buffer_size = 0;
|
|
||||||
static unsigned char jpg_buffer[ZM_MAX_IMAGE_SIZE];
|
|
||||||
|
|
||||||
image->EncodeJpeg( jpg_buffer, &jpg_buffer_size, (alarm_frame&&(config.jpeg_alarm_file_quality>config.jpeg_file_quality))?config.jpeg_alarm_file_quality:config.jpeg_file_quality );
|
|
||||||
|
|
||||||
static FrameHeader frame_header;
|
|
||||||
|
|
||||||
frame_header.event_id = id;
|
|
||||||
if ( config.use_deep_storage )
|
|
||||||
frame_header.event_time = start_time.tv_sec;
|
|
||||||
frame_header.frame_id = frames;
|
|
||||||
frame_header.alarm_frame = alarm_frame;
|
|
||||||
frame_header.image_length = jpg_buffer_size;
|
|
||||||
|
|
||||||
struct iovec iovecs[2];
|
|
||||||
iovecs[0].iov_base = &frame_header;
|
|
||||||
iovecs[0].iov_len = sizeof(frame_header);
|
|
||||||
iovecs[1].iov_base = jpg_buffer;
|
|
||||||
iovecs[1].iov_len = jpg_buffer_size;
|
|
||||||
|
|
||||||
ssize_t writev_size = sizeof(frame_header)+jpg_buffer_size;
|
|
||||||
ssize_t writev_result = writev( sd, iovecs, sizeof(iovecs)/sizeof(*iovecs));
|
|
||||||
if ( writev_result != writev_size )
|
|
||||||
{
|
|
||||||
if ( writev_result < 0 )
|
|
||||||
{
|
|
||||||
if ( errno == EAGAIN )
|
|
||||||
{
|
|
||||||
Warning( "Blocking write detected" );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Error( "Can't write frame: %s", strerror(errno) );
|
|
||||||
close( sd );
|
|
||||||
sd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Error( "Incomplete frame write: %zd of %zd bytes written", writev_result, writev_size );
|
|
||||||
close( sd );
|
|
||||||
sd = -1;
|
|
||||||
}
|
|
||||||
return( false );
|
|
||||||
}
|
|
||||||
Debug( 1, "Wrote frame image, %d bytes", jpg_buffer_size );
|
|
||||||
|
|
||||||
return( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame )
|
bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame )
|
||||||
{
|
{
|
||||||
Image* ImgToWrite;
|
Image* ImgToWrite;
|
||||||
|
@ -364,11 +233,9 @@ bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char
|
||||||
else
|
else
|
||||||
ImgToWrite=image;
|
ImgToWrite=image;
|
||||||
|
|
||||||
if ( !config.opt_frame_server || !SendFrameImage(ImgToWrite, alarm_frame) )
|
int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use, zero is default
|
||||||
{
|
ImgToWrite->WriteJpeg( event_file, thisquality, (monitor->Exif() ? timestamp : (timeval){0,0}) ); // exif is only timestamp at present this switches on or off for write
|
||||||
int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use, zero is default
|
|
||||||
ImgToWrite->WriteJpeg( event_file, thisquality, (monitor->Exif() ? timestamp : (timeval){0,0}) ); // exif is only timestamp at present this switches on or off for write
|
|
||||||
}
|
|
||||||
if(ts_image) delete(ts_image); // clean up if used.
|
if(ts_image) delete(ts_image); // clean up if used.
|
||||||
return( true );
|
return( true );
|
||||||
}
|
}
|
||||||
|
|
1508
src/zm_image.cpp
|
@ -54,7 +54,7 @@ extern imgbufcpy_fptr_t fptr_imgbufcpy;
|
||||||
|
|
||||||
/* Should be called from Image class functions */
|
/* Should be called from Image class functions */
|
||||||
inline static uint8_t* AllocBuffer(size_t p_bufsize) {
|
inline static uint8_t* AllocBuffer(size_t p_bufsize) {
|
||||||
uint8_t* buffer = (uint8_t*)zm_mallocaligned(16,p_bufsize);
|
uint8_t* buffer = (uint8_t*)zm_mallocaligned(64,p_bufsize);
|
||||||
if(buffer == NULL)
|
if(buffer == NULL)
|
||||||
Fatal("Memory allocation failed: %s",strerror(errno));
|
Fatal("Memory allocation failed: %s",strerror(errno));
|
||||||
|
|
||||||
|
@ -264,6 +264,7 @@ public:
|
||||||
/* Blend functions */
|
/* Blend functions */
|
||||||
void sse2_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent);
|
void sse2_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent);
|
||||||
void std_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent);
|
void std_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent);
|
||||||
|
void neon32_armv7_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent);
|
||||||
void std_blend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent);
|
void std_blend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent);
|
||||||
|
|
||||||
/* Delta functions */
|
/* Delta functions */
|
||||||
|
@ -274,6 +275,11 @@ void std_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result,
|
||||||
void std_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
void std_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||||
void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||||
void std_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
void std_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||||
|
void neon32_armv7_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||||
|
void neon32_armv7_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||||
|
void neon32_armv7_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||||
|
void neon32_armv7_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||||
|
void neon32_armv7_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||||
void sse2_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
void sse2_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||||
void sse2_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
void sse2_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||||
void sse2_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
void sse2_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count);
|
||||||
|
@ -293,6 +299,9 @@ void std_convert_argb_gray8(const uint8_t* col1, uint8_t* result, unsigned long
|
||||||
void std_convert_abgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
void std_convert_abgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||||
void std_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
void std_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||||
void ssse3_convert_rgba_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
void ssse3_convert_rgba_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||||
|
void ssse3_convert_bgra_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||||
|
void ssse3_convert_argb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||||
|
void ssse3_convert_abgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||||
void ssse3_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
void ssse3_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||||
void zm_convert_yuyv_rgb(const uint8_t* col1, uint8_t* result, unsigned long count);
|
void zm_convert_yuyv_rgb(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||||
void zm_convert_yuyv_rgba(const uint8_t* col1, uint8_t* result, unsigned long count);
|
void zm_convert_yuyv_rgba(const uint8_t* col1, uint8_t* result, unsigned long count);
|
||||||
|
@ -309,8 +318,3 @@ void std_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int thre
|
||||||
void std_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
void std_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
||||||
void std_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
void std_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
||||||
void std_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
void std_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
||||||
void ssse3_deinterlace_4field_gray8(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
|
||||||
void ssse3_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
|
||||||
void ssse3_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
|
||||||
void ssse3_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
|
||||||
void ssse3_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height);
|
|
||||||
|
|
|
@ -182,8 +182,8 @@ int LibvlcCamera::PrimeCapture()
|
||||||
|
|
||||||
mLibvlcData.bufferSize = width * height * mBpp;
|
mLibvlcData.bufferSize = width * height * mBpp;
|
||||||
// Libvlc wants 32 byte alignment for images (should in theory do this for all image lines)
|
// Libvlc wants 32 byte alignment for images (should in theory do this for all image lines)
|
||||||
mLibvlcData.buffer = (uint8_t*)zm_mallocaligned(32, mLibvlcData.bufferSize);
|
mLibvlcData.buffer = (uint8_t*)zm_mallocaligned(64, mLibvlcData.bufferSize);
|
||||||
mLibvlcData.prevBuffer = (uint8_t*)zm_mallocaligned(32, mLibvlcData.bufferSize);
|
mLibvlcData.prevBuffer = (uint8_t*)zm_mallocaligned(64, mLibvlcData.bufferSize);
|
||||||
|
|
||||||
mLibvlcData.newImage.setValueImmediate(false);
|
mLibvlcData.newImage.setValueImmediate(false);
|
||||||
|
|
||||||
|
|
|
@ -393,7 +393,7 @@ Monitor::Monitor(
|
||||||
+ sizeof(TriggerData)
|
+ sizeof(TriggerData)
|
||||||
+ (image_buffer_count*sizeof(struct timeval))
|
+ (image_buffer_count*sizeof(struct timeval))
|
||||||
+ (image_buffer_count*camera->ImageSize())
|
+ (image_buffer_count*camera->ImageSize())
|
||||||
+ 64; /* Padding used to permit aligning the images buffer to 16 byte boundary */
|
+ 64; /* Padding used to permit aligning the images buffer to 64 byte boundary */
|
||||||
|
|
||||||
Debug( 1, "mem.size=%d", mem_size );
|
Debug( 1, "mem.size=%d", mem_size );
|
||||||
mem_ptr = NULL;
|
mem_ptr = NULL;
|
||||||
|
@ -569,10 +569,10 @@ bool Monitor::connect() {
|
||||||
struct timeval *shared_timestamps = (struct timeval *)((char *)trigger_data + sizeof(TriggerData));
|
struct timeval *shared_timestamps = (struct timeval *)((char *)trigger_data + sizeof(TriggerData));
|
||||||
unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval)));
|
unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval)));
|
||||||
|
|
||||||
if(((unsigned long)shared_images % 16) != 0) {
|
if(((unsigned long)shared_images % 64) != 0) {
|
||||||
/* Align images buffer to nearest 16 byte boundary */
|
/* Align images buffer to nearest 64 byte boundary */
|
||||||
Debug(3,"Aligning shared memory images to the next 16 byte boundary");
|
Debug(3,"Aligning shared memory images to the next 64 byte boundary");
|
||||||
shared_images = (uint8_t*)((unsigned long)shared_images + (16 - ((unsigned long)shared_images % 16)));
|
shared_images = (uint8_t*)((unsigned long)shared_images + (64 - ((unsigned long)shared_images % 64)));
|
||||||
}
|
}
|
||||||
image_buffer = new Snapshot[image_buffer_count];
|
image_buffer = new Snapshot[image_buffer_count];
|
||||||
for ( int i = 0; i < image_buffer_count; i++ )
|
for ( int i = 0; i < image_buffer_count; i++ )
|
||||||
|
|
|
@ -24,12 +24,16 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#if defined(__arm__)
|
||||||
|
#include <sys/auxv.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_CURL_CURL_H
|
#ifdef HAVE_CURL_CURL_H
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned int sseversion = 0;
|
unsigned int sseversion = 0;
|
||||||
|
unsigned int neonversion = 0;
|
||||||
|
|
||||||
std::string trimSet(std::string str, std::string trimset) {
|
std::string trimSet(std::string str, std::string trimset) {
|
||||||
// Trim Both leading and trailing sets
|
// Trim Both leading and trailing sets
|
||||||
|
@ -238,30 +242,59 @@ int pairsplit(const char* string, const char delim, std::string& name, std::stri
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sets sse_version */
|
/* Detect special hardware features, such as SIMD instruction sets */
|
||||||
void ssedetect() {
|
void hwcaps_detect() {
|
||||||
|
neonversion = 0;
|
||||||
|
sseversion = 0;
|
||||||
#if (defined(__i386__) || defined(__x86_64__))
|
#if (defined(__i386__) || defined(__x86_64__))
|
||||||
/* x86 or x86-64 processor */
|
/* x86 or x86-64 processor */
|
||||||
uint32_t r_edx, r_ecx;
|
uint32_t r_edx, r_ecx, r_ebx;
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
#if defined(__i386__)
|
"push %%rbx\n\t"
|
||||||
"pushl %%ebx;\n\t"
|
"mov $0x0,%%ecx\n\t"
|
||||||
#endif
|
"mov $0x7,%%eax\n\t"
|
||||||
|
"cpuid\n\t"
|
||||||
|
"push %%rbx\n\t"
|
||||||
"mov $0x1,%%eax\n\t"
|
"mov $0x1,%%eax\n\t"
|
||||||
"cpuid\n\t"
|
"cpuid\n\t"
|
||||||
#if defined(__i386__)
|
"pop %%rax\n\t"
|
||||||
"popl %%ebx;\n\t"
|
"pop %%rbx\n\t"
|
||||||
#endif
|
: "=d" (r_edx), "=c" (r_ecx), "=a" (r_ebx)
|
||||||
: "=d" (r_edx), "=c" (r_ecx)
|
:
|
||||||
:
|
:
|
||||||
: "%eax"
|
|
||||||
#if !defined(__i386__)
|
|
||||||
, "%ebx"
|
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
|
#else
|
||||||
if (r_ecx & 0x00000200) {
|
__asm__ __volatile__(
|
||||||
|
"push %%ebx\n\t"
|
||||||
|
"mov $0x0,%%ecx\n\t"
|
||||||
|
"mov $0x7,%%eax\n\t"
|
||||||
|
"cpuid\n\t"
|
||||||
|
"push %%ebx\n\t"
|
||||||
|
"mov $0x1,%%eax\n\t"
|
||||||
|
"cpuid\n\t"
|
||||||
|
"pop %%eax\n\t"
|
||||||
|
"pop %%ebx\n\t"
|
||||||
|
: "=d" (r_edx), "=c" (r_ecx), "=a" (r_ebx)
|
||||||
|
:
|
||||||
|
:
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (r_ebx & 0x00000020) {
|
||||||
|
sseversion = 52; /* AVX2 */
|
||||||
|
Debug(1,"Detected a x86\\x86-64 processor with AVX2");
|
||||||
|
} else if (r_ecx & 0x10000000) {
|
||||||
|
sseversion = 51; /* AVX */
|
||||||
|
Debug(1,"Detected a x86\\x86-64 processor with AVX");
|
||||||
|
} else if (r_ecx & 0x00100000) {
|
||||||
|
sseversion = 42; /* SSE4.2 */
|
||||||
|
Debug(1,"Detected a x86\\x86-64 processor with SSE4.2");
|
||||||
|
} else if (r_ecx & 0x00080000) {
|
||||||
|
sseversion = 41; /* SSE4.1 */
|
||||||
|
Debug(1,"Detected a x86\\x86-64 processor with SSE4.1");
|
||||||
|
} else if (r_ecx & 0x00000200) {
|
||||||
sseversion = 35; /* SSSE3 */
|
sseversion = 35; /* SSSE3 */
|
||||||
Debug(1,"Detected a x86\\x86-64 processor with SSSE3");
|
Debug(1,"Detected a x86\\x86-64 processor with SSSE3");
|
||||||
} else if (r_ecx & 0x00000001) {
|
} else if (r_ecx & 0x00000001) {
|
||||||
|
@ -276,12 +309,20 @@ void ssedetect() {
|
||||||
} else {
|
} else {
|
||||||
sseversion = 0;
|
sseversion = 0;
|
||||||
Debug(1,"Detected a x86\\x86-64 processor");
|
Debug(1,"Detected a x86\\x86-64 processor");
|
||||||
|
}
|
||||||
|
#elif defined(__arm__)
|
||||||
|
// ARM processor
|
||||||
|
// To see if it supports NEON, we need to get that information from the kernel
|
||||||
|
unsigned long auxval = getauxval(AT_HWCAP);
|
||||||
|
if (auxval & HWCAP_ARM_NEON) {
|
||||||
|
Debug(1,"Detected ARM processor with Neon");
|
||||||
|
neonversion = 1;
|
||||||
|
} else {
|
||||||
|
Debug(1,"Detected ARM processor");
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* Non x86 or x86-64 processor, SSE2 is not available */
|
// Unknown processor
|
||||||
Debug(1,"Detected a non x86\\x86-64 processor");
|
Debug(1,"Detected unknown processor architecture");
|
||||||
sseversion = 0;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,11 +54,12 @@ inline int min( int a, int b )
|
||||||
return( a<=b?a:b );
|
return( a<=b?a:b );
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssedetect();
|
|
||||||
void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes);
|
void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes);
|
||||||
void timespec_diff(struct timespec *start, struct timespec *end, struct timespec *diff);
|
void timespec_diff(struct timespec *start, struct timespec *end, struct timespec *diff);
|
||||||
|
|
||||||
|
void hwcaps_detect();
|
||||||
extern unsigned int sseversion;
|
extern unsigned int sseversion;
|
||||||
|
extern unsigned int neonversion;
|
||||||
|
|
||||||
std::string UriDecode( const std::string &encoded );
|
std::string UriDecode( const std::string &encoded );
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ int main( int argc, char *argv[] )
|
||||||
|
|
||||||
logInit( log_id_string );
|
logInit( log_id_string );
|
||||||
|
|
||||||
ssedetect();
|
hwcaps_detect();
|
||||||
|
|
||||||
Monitor *monitor = Monitor::Load( id, true, Monitor::ANALYSIS );
|
Monitor *monitor = Monitor::Load( id, true, Monitor::ANALYSIS );
|
||||||
|
|
||||||
|
@ -141,11 +141,6 @@ int main( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
Info( "In mode %d/%d, warming up", monitor->GetFunction(), monitor->Enabled() );
|
Info( "In mode %d/%d, warming up", monitor->GetFunction(), monitor->Enabled() );
|
||||||
|
|
||||||
if ( config.opt_frame_server )
|
|
||||||
{
|
|
||||||
Event::OpenFrameSocket( monitor->Id() );
|
|
||||||
}
|
|
||||||
|
|
||||||
zmSetDefaultHupHandler();
|
zmSetDefaultHupHandler();
|
||||||
zmSetDefaultTermHandler();
|
zmSetDefaultTermHandler();
|
||||||
zmSetDefaultDieHandler();
|
zmSetDefaultDieHandler();
|
||||||
|
|
|
@ -206,7 +206,7 @@ int main( int argc, char *argv[] )
|
||||||
|
|
||||||
logInit( log_id_string );
|
logInit( log_id_string );
|
||||||
|
|
||||||
ssedetect();
|
hwcaps_detect();
|
||||||
|
|
||||||
Monitor **monitors = 0;
|
Monitor **monitors = 0;
|
||||||
int n_monitors = 0;
|
int n_monitors = 0;
|
||||||
|
|
350
src/zmf.cpp
|
@ -1,350 +0,0 @@
|
||||||
//
|
|
||||||
// ZoneMinder Image File Writer Implementation, $Date$, $Revision$
|
|
||||||
// Copyright (C) 2001-2008 Philip Coombes
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU General Public License
|
|
||||||
// as published by the Free Software Foundation; either version 2
|
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
//
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
zmf - The ZoneMinder Frame daemon
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
zmf -m <monitor_id>
|
|
||||||
zmf --monitor <monitor_id>
|
|
||||||
zmf -h
|
|
||||||
zmf --help
|
|
||||||
zmf -v
|
|
||||||
zmf --version
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
This is an optional daemon that can run in concert with the Analysis daemon and
|
|
||||||
whose function it is to actually write captured frames to disk. This frees up
|
|
||||||
the Analysis daemon to do more analysis (!) and so keep up with the Capture
|
|
||||||
daemon better. If it isn't running or dies then the Analysis daemon just writes
|
|
||||||
them itself.
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
-m, --monitor_id - ID of the monitor to use
|
|
||||||
-h, --help - Display usage information
|
|
||||||
-v, --version - Print the installed version of ZoneMinder
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include "zm.h"
|
|
||||||
#include "zm_db.h"
|
|
||||||
#include "zm_signal.h"
|
|
||||||
#include "zm_monitor.h"
|
|
||||||
|
|
||||||
#include "zmf.h"
|
|
||||||
|
|
||||||
int OpenSocket( int monitor_id )
|
|
||||||
{
|
|
||||||
int sd = socket( AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if ( sd < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't create socket: %s", strerror(errno) );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
char sock_path[PATH_MAX] = "";
|
|
||||||
snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id );
|
|
||||||
if ( unlink( sock_path ) < 0 )
|
|
||||||
{
|
|
||||||
Warning( "Can't unlink '%s': %s", sock_path, strerror(errno) );
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_un addr;
|
|
||||||
|
|
||||||
strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) );
|
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
|
|
||||||
if ( bind( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't bind: %s", strerror(errno) );
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( listen( sd, SOMAXCONN ) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't listen: %s", strerror(errno) );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_un rem_addr;
|
|
||||||
socklen_t rem_addr_len = sizeof(rem_addr);
|
|
||||||
int new_sd = -1;
|
|
||||||
if ( (new_sd = accept( sd, (struct sockaddr *)&rem_addr, &rem_addr_len )) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't accept: %s", strerror(errno) );
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
close( sd );
|
|
||||||
|
|
||||||
sd = new_sd;
|
|
||||||
|
|
||||||
Info( "Frame server socket open, awaiting images" );
|
|
||||||
return( sd );
|
|
||||||
}
|
|
||||||
|
|
||||||
int ReopenSocket( int &sd, int monitor_id )
|
|
||||||
{
|
|
||||||
close( sd );
|
|
||||||
return( sd = OpenSocket( monitor_id ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Usage()
|
|
||||||
{
|
|
||||||
fprintf( stderr, "zmf -m <monitor_id>\n" );
|
|
||||||
fprintf( stderr, "Options:\n" );
|
|
||||||
fprintf( stderr, " -m, --monitor <monitor_id> : Specify which monitor to use\n" );
|
|
||||||
fprintf( stderr, " -h, --help : This screen\n" );
|
|
||||||
fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" );
|
|
||||||
exit( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int main( int argc, char *argv[] )
|
|
||||||
{
|
|
||||||
self = argv[0];
|
|
||||||
|
|
||||||
srand( getpid() * time( 0 ) );
|
|
||||||
|
|
||||||
int id = -1;
|
|
||||||
|
|
||||||
static struct option long_options[] = {
|
|
||||||
{"monitor", 1, 0, 'm'},
|
|
||||||
{"help", 0, 0, 'h'},
|
|
||||||
{"version", 0, 0, 'v'},
|
|
||||||
{0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
int option_index = 0;
|
|
||||||
|
|
||||||
int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index);
|
|
||||||
if (c == -1)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case 'm':
|
|
||||||
id = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
case '?':
|
|
||||||
Usage();
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
std::cout << ZM_VERSION << "\n";
|
|
||||||
exit(0);
|
|
||||||
default:
|
|
||||||
//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optind < argc)
|
|
||||||
{
|
|
||||||
fprintf( stderr, "Extraneous options, " );
|
|
||||||
while (optind < argc)
|
|
||||||
printf ("%s ", argv[optind++]);
|
|
||||||
printf ("\n");
|
|
||||||
Usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( id < 0 )
|
|
||||||
{
|
|
||||||
fprintf( stderr, "Bogus monitor %d\n", id );
|
|
||||||
Usage();
|
|
||||||
exit( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
char log_id_string[16];
|
|
||||||
snprintf( log_id_string, sizeof(log_id_string), "m%d", id );
|
|
||||||
|
|
||||||
zmLoadConfig();
|
|
||||||
|
|
||||||
logInit( "zmf" );
|
|
||||||
|
|
||||||
ssedetect();
|
|
||||||
|
|
||||||
Monitor *monitor = Monitor::Load( id, false, Monitor::QUERY );
|
|
||||||
|
|
||||||
if ( !monitor )
|
|
||||||
{
|
|
||||||
fprintf( stderr, "Can't find monitor with id of %d\n", id );
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
char capt_path[PATH_MAX];
|
|
||||||
char anal_path[PATH_MAX];
|
|
||||||
snprintf( capt_path, sizeof(capt_path), "%s/%d/%%s/%%0%dd-capture.jpg", config.dir_events, monitor->Id(), config.event_image_digits );
|
|
||||||
snprintf( anal_path, sizeof(anal_path), "%s/%d/%%s/%%0%dd-analyse.jpg", config.dir_events, monitor->Id(), config.event_image_digits );
|
|
||||||
zmSetDefaultTermHandler();
|
|
||||||
zmSetDefaultDieHandler();
|
|
||||||
|
|
||||||
sigset_t block_set;
|
|
||||||
sigemptyset( &block_set );
|
|
||||||
|
|
||||||
int sd = OpenSocket( monitor->Id() );
|
|
||||||
|
|
||||||
FrameHeader frame_header = { 0, 0, false, 0 };
|
|
||||||
//unsigned char *image_data = 0;
|
|
||||||
|
|
||||||
fd_set rfds;
|
|
||||||
|
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
while( 1 )
|
|
||||||
{
|
|
||||||
struct timeval temp_timeout = timeout;
|
|
||||||
|
|
||||||
FD_ZERO(&rfds);
|
|
||||||
FD_SET(sd, &rfds);
|
|
||||||
int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout );
|
|
||||||
if( n_found == 0 )
|
|
||||||
{
|
|
||||||
Debug( 1, "Select timed out" );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if ( n_found < 0)
|
|
||||||
{
|
|
||||||
Error( "Select error: %s", strerror(errno) );
|
|
||||||
ReopenSocket( sd, monitor->Id() );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sigprocmask( SIG_BLOCK, &block_set, 0 );
|
|
||||||
|
|
||||||
int n_bytes = read( sd, &frame_header, sizeof(frame_header) );
|
|
||||||
if ( n_bytes != sizeof(frame_header) )
|
|
||||||
{
|
|
||||||
if ( n_bytes < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't read frame header: %s", strerror(errno) );
|
|
||||||
}
|
|
||||||
else if ( n_bytes > 0 )
|
|
||||||
{
|
|
||||||
Error( "Incomplete read of frame header, %d bytes only", n_bytes );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Warning( "Socket closed at remote end" );
|
|
||||||
}
|
|
||||||
ReopenSocket( sd, monitor->Id() );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length );
|
|
||||||
static unsigned char image_data[ZM_MAX_IMAGE_SIZE];
|
|
||||||
|
|
||||||
// Read for pipe and loop until bytes expected have been read or an error occurs
|
|
||||||
int bytes_read = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
n_bytes = read( sd, image_data+bytes_read, frame_header.image_length-bytes_read );
|
|
||||||
if (n_bytes < 0) break; // break on error
|
|
||||||
if (n_bytes < (int)frame_header.image_length)
|
|
||||||
{
|
|
||||||
// print some informational messages
|
|
||||||
if (bytes_read == 0)
|
|
||||||
{
|
|
||||||
Debug(4,"Image read : Short read %d bytes of %d expected bytes",n_bytes,frame_header.image_length);
|
|
||||||
}
|
|
||||||
else if (bytes_read+n_bytes == (int)frame_header.image_length)
|
|
||||||
{
|
|
||||||
Debug(5,"Image read : Read rest of short read: %d bytes read total of %d bytes",n_bytes,frame_header.image_length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug(6,"Image read : continuing, read %d bytes (%d so far)", n_bytes, bytes_read+n_bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bytes_read+= n_bytes;
|
|
||||||
} while (n_bytes>0 && (bytes_read < (ssize_t)frame_header.image_length) );
|
|
||||||
|
|
||||||
// Print errors if there was a problem
|
|
||||||
if ( n_bytes < 1 )
|
|
||||||
{
|
|
||||||
Error( "Only read %d bytes of %d\n", bytes_read, frame_header.image_length);
|
|
||||||
if ( n_bytes < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't read frame image data: %s", strerror(errno) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Warning( "Socket closed at remote end" );
|
|
||||||
}
|
|
||||||
ReopenSocket( sd, monitor->Id() );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char subpath[PATH_MAX] = "";
|
|
||||||
if ( config.use_deep_storage )
|
|
||||||
{
|
|
||||||
struct tm *time = localtime( &frame_header.event_time );
|
|
||||||
snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf( subpath, sizeof(subpath), "%ld", frame_header.event_id );
|
|
||||||
}
|
|
||||||
|
|
||||||
static char path[PATH_MAX] = "";
|
|
||||||
snprintf( path, sizeof(path), frame_header.alarm_frame?anal_path:capt_path, subpath, frame_header.frame_id );
|
|
||||||
Debug( 1, "Got image, writing to %s", path );
|
|
||||||
|
|
||||||
FILE *fd = 0;
|
|
||||||
if ( (fd = fopen( path, "w" )) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't fopen '%s': %s", path, strerror(errno) );
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
if ( 0 == fwrite( image_data, frame_header.image_length, 1, fd ) )
|
|
||||||
{
|
|
||||||
Error( "Can't fwrite image data: %s", strerror(errno) );
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
fclose( fd );
|
|
||||||
|
|
||||||
sigprocmask( SIG_UNBLOCK, &block_set, 0 );
|
|
||||||
}
|
|
||||||
logTerm();
|
|
||||||
zmDbClose();
|
|
||||||
}
|
|
32
src/zmf.h
|
@ -1,32 +0,0 @@
|
||||||
//
|
|
||||||
// ZoneMinder Image File Write Class Interface, $Date$, $Revision$
|
|
||||||
// Copyright (C) 2001-2008 Philip Coombes
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU General Public License
|
|
||||||
// as published by the Free Software Foundation; either version 2
|
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef ZMFILE_H
|
|
||||||
#define ZMFILE_H
|
|
||||||
|
|
||||||
struct FrameHeader
|
|
||||||
{
|
|
||||||
unsigned long event_id;
|
|
||||||
time_t event_time;
|
|
||||||
unsigned long frame_id;
|
|
||||||
bool alarm_frame;
|
|
||||||
unsigned long image_length;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ZMFILE_H
|
|
|
@ -91,7 +91,7 @@ int main( int argc, const char *argv[] )
|
||||||
|
|
||||||
logInit( "zms" );
|
logInit( "zms" );
|
||||||
|
|
||||||
ssedetect();
|
hwcaps_detect();
|
||||||
|
|
||||||
zmSetDefaultTermHandler();
|
zmSetDefaultTermHandler();
|
||||||
zmSetDefaultDieHandler();
|
zmSetDefaultDieHandler();
|
||||||
|
@ -180,11 +180,11 @@ int main( int argc, const char *argv[] )
|
||||||
{
|
{
|
||||||
if ( !strcmp( name, "user" ) )
|
if ( !strcmp( name, "user" ) )
|
||||||
{
|
{
|
||||||
username = UriDecode(value);
|
username = UriDecode( value );
|
||||||
}
|
}
|
||||||
if ( !strcmp( name, "pass" ) )
|
if ( !strcmp( name, "pass" ) )
|
||||||
{
|
{
|
||||||
password = UriDecode( password );
|
password = UriDecode( value );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,252 +0,0 @@
|
||||||
//
|
|
||||||
// ZoneMinder Streamer, $Date: 2010-10-14 23:21:00 +0200 (Thu, 14 Oct 2010) $
|
|
||||||
// Copyright (C) 2001-2010 Philip Coombes, Chris Kistner
|
|
||||||
//
|
|
||||||
// This program is based on revision 3143 of
|
|
||||||
// http://svn.zoneminder.com/svn/zm/trunk/src/zms.cpp
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU General Public License
|
|
||||||
// as published by the Free Software Foundation; either version 2
|
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
zmstreamer - eyeZM video streamer
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
zmstreamer -e <mode>
|
|
||||||
zmstreamer -o <format>
|
|
||||||
zmstreamer -u <buffer size>
|
|
||||||
zmstreamer -f <maximum fps>
|
|
||||||
zmstreamer -s <scale>
|
|
||||||
zmstreamer -b <bitrate in bps>
|
|
||||||
zmstreamer -m <monitor id>
|
|
||||||
zmstreamer -d <debug mode>
|
|
||||||
zmstreamer -i
|
|
||||||
zmstreamer -?
|
|
||||||
zmstreamer -h
|
|
||||||
zmstreamer -v
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
*DEPRECIATED* The xml skin and all files associated with the xml skin are now
|
|
||||||
depreciated. Please use the ZoneMinder API instead.
|
|
||||||
|
|
||||||
This binary works in conjunction with the XML skin to stream video to iPhones
|
|
||||||
running the eyeZm app.
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
-e <mode> - Specify output mode: mpeg/jpg/zip/single/raw.
|
|
||||||
-o <format> - Specify output format.
|
|
||||||
-u <buffer size> - Specify buffer size in ms.
|
|
||||||
-f <maximum fps> - Specify maximum framerate.
|
|
||||||
-s <scale> - Specify scale.
|
|
||||||
-b <bitrate in bps> - Specify bitrate.
|
|
||||||
-m <monitor id> - Specify monitor id.
|
|
||||||
-d <debug mode> - 0 = off, 1 = no streaming, 2 = with streaming.
|
|
||||||
-i, -?, -h - Display usage information
|
|
||||||
-v - Print the installed version of ZoneMinder
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <sys/ipc.h>
|
|
||||||
#include <sys/msg.h>
|
|
||||||
|
|
||||||
#include "zm.h"
|
|
||||||
#include "zm_db.h"
|
|
||||||
#include "zm_user.h"
|
|
||||||
#include "zm_signal.h"
|
|
||||||
#include "zm_monitor.h"
|
|
||||||
#include "zm_stream.h"
|
|
||||||
|
|
||||||
// Possible command-line options
|
|
||||||
#define OPTIONS "e:o:u:f:s:b:m:d:i:?:h:v"
|
|
||||||
|
|
||||||
// Default ZMS values
|
|
||||||
#define ZMS_DEFAULT_DEBUG 0
|
|
||||||
#define ZMS_DEFAULT_ID 1
|
|
||||||
#define ZMS_DEFAULT_BITRATE 100000
|
|
||||||
#define ZMS_DEFAULT_SCALE 100
|
|
||||||
#define ZMS_DEFAULT_MODE "mpeg"
|
|
||||||
#define ZMS_DEFAULT_FORMAT "asf"
|
|
||||||
#define ZMS_DEFAULT_FPS 25.0
|
|
||||||
#define ZMS_DEFAULT_BUFFER 1000
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
self = argv[0];
|
|
||||||
// Set initial values to the default values
|
|
||||||
int debug = ZMS_DEFAULT_DEBUG;
|
|
||||||
int id = ZMS_DEFAULT_ID;
|
|
||||||
int bitrate = ZMS_DEFAULT_BITRATE;
|
|
||||||
int scale = ZMS_DEFAULT_SCALE;
|
|
||||||
char mode[32];
|
|
||||||
sprintf(mode, "%s", ZMS_DEFAULT_MODE);
|
|
||||||
char format[32];
|
|
||||||
sprintf(format, "%s", ZMS_DEFAULT_FORMAT);
|
|
||||||
double maxfps = ZMS_DEFAULT_FPS;
|
|
||||||
int buffer = ZMS_DEFAULT_BUFFER;
|
|
||||||
|
|
||||||
// Parse command-line options
|
|
||||||
int arg;
|
|
||||||
while ((arg = getopt(argc, argv, OPTIONS)) != -1) {
|
|
||||||
switch (arg) {
|
|
||||||
case 'e':
|
|
||||||
sprintf(mode, "%s", optarg);
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
sprintf(format, "%s", optarg);
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
buffer = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
maxfps = atof(optarg);
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
scale = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
bitrate = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
id = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
debug = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
case 'i':
|
|
||||||
case '?':
|
|
||||||
printf("-e <mode> : Specify output mode: mpeg/jpg/zip/single/raw. Default = %s\n", ZMS_DEFAULT_MODE);
|
|
||||||
printf("-o <format> : Specify output format. Default = %s\n", ZMS_DEFAULT_FORMAT);
|
|
||||||
printf("-u <buffer size> : Specify buffer size in ms. Default = %d\n", ZMS_DEFAULT_BUFFER);
|
|
||||||
printf("-f <maximum fps> : Specify maximum framerate. Default = %lf\n", ZMS_DEFAULT_FPS);
|
|
||||||
printf("-s <scale> : Specify scale. Default = %d\n", ZMS_DEFAULT_SCALE);
|
|
||||||
printf("-b <bitrate in bps> : Specify bitrate. Default = %d\n", ZMS_DEFAULT_BITRATE);
|
|
||||||
printf("-m <monitor id> : Specify monitor id. Default = %d\n", ZMS_DEFAULT_ID);
|
|
||||||
printf("-d <debug mode> : 0 = off, 1 = no streaming, 2 = with streaming. Default = 0\n");
|
|
||||||
printf("-i or -? or -h: This information\n");
|
|
||||||
printf("-v : This installed version of ZoneMinder\n");
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
case 'v':
|
|
||||||
std::cout << ZM_VERSION << "\n";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set stream type
|
|
||||||
StreamBase::StreamType streamtype;
|
|
||||||
if (!strcasecmp("raw", mode))
|
|
||||||
streamtype = MonitorStream::STREAM_RAW;
|
|
||||||
else if (!strcasecmp("mpeg", mode))
|
|
||||||
streamtype = MonitorStream::STREAM_MPEG;
|
|
||||||
else if (!strcasecmp("jpg", mode))
|
|
||||||
streamtype = MonitorStream::STREAM_JPEG;
|
|
||||||
else if (!strcasecmp("single", mode))
|
|
||||||
streamtype = MonitorStream::STREAM_SINGLE;
|
|
||||||
else if (!strcasecmp("zip", mode))
|
|
||||||
streamtype = MonitorStream::STREAM_ZIP;
|
|
||||||
else
|
|
||||||
streamtype = MonitorStream::STREAM_MPEG;
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
// Show stream parameters
|
|
||||||
printf("Stream parameters:\n");
|
|
||||||
switch (streamtype) {
|
|
||||||
case MonitorStream::STREAM_MPEG:
|
|
||||||
printf("Output mode (-e) = %s\n", "mpeg");
|
|
||||||
printf("Output format (-o) = %s\n", format);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Output mode (-e) = %s\n", mode);
|
|
||||||
}
|
|
||||||
printf("Buffer size (-u) = %d ms\n", buffer);
|
|
||||||
printf("Maximum FPS (-f) = %lf FPS\n", maxfps);
|
|
||||||
printf("Scale (-s) = %d%%\n", scale);
|
|
||||||
printf("Bitrate (-b) = %d bps\n", bitrate);
|
|
||||||
printf("Monitor Id (-m) = %d\n", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
// Set ZM debugger to print to stdout
|
|
||||||
printf("Setting up ZoneMinder debugger to print to stdout...");
|
|
||||||
setenv("ZM_DBG_PRINT", "1", 1);
|
|
||||||
printf("Done.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loading ZM configurations
|
|
||||||
printf("Loading ZoneMinder configurations...");
|
|
||||||
zmLoadConfig();
|
|
||||||
printf("Done.\n");
|
|
||||||
|
|
||||||
logInit("zmstreamer");
|
|
||||||
|
|
||||||
ssedetect();
|
|
||||||
|
|
||||||
// Setting stream parameters
|
|
||||||
MonitorStream stream;
|
|
||||||
stream.setStreamScale(scale); // default = 100 (scale)
|
|
||||||
stream.setStreamReplayRate(100); // default = 100 (rate)
|
|
||||||
stream.setStreamMaxFPS(maxfps); // default = 10 (maxfps)
|
|
||||||
if (debug) stream.setStreamTTL(1);
|
|
||||||
else stream.setStreamTTL(0); // default = 0 (ttl)
|
|
||||||
stream.setStreamQueue(0); // default = 0 (connkey)
|
|
||||||
stream.setStreamBuffer(buffer); // default = 0 (buffer)
|
|
||||||
stream.setStreamStart(id); // default = 0 (monitor_id)
|
|
||||||
stream.setStreamType(streamtype);
|
|
||||||
if (streamtype == MonitorStream::STREAM_MPEG) {
|
|
||||||
#if HAVE_LIBAVCODEC
|
|
||||||
if (debug) printf("HAVE_LIBAVCODEC is set\n");
|
|
||||||
stream.setStreamFormat(format); // default = "" (format)
|
|
||||||
stream.setStreamBitrate(bitrate); // default = 100000 (bitrate)
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n");
|
|
||||||
logTerm();
|
|
||||||
zmDbClose();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug != 1) {
|
|
||||||
if (debug) printf("Running stream...");
|
|
||||||
|
|
||||||
// Output headers
|
|
||||||
fprintf(stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION);
|
|
||||||
time_t now = time(0);
|
|
||||||
char date_string[64];
|
|
||||||
strftime(date_string, sizeof (date_string) - 1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
|
|
||||||
fprintf(stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n");
|
|
||||||
fprintf(stdout, "Last-Modified: %s\r\n", date_string);
|
|
||||||
fprintf(stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n");
|
|
||||||
fprintf(stdout, "Cache-Control: post-check=0, pre-check=0\r\n");
|
|
||||||
fprintf(stdout, "Pragma: no-cache\r\n");
|
|
||||||
|
|
||||||
// Run stream
|
|
||||||
stream.runStream();
|
|
||||||
}
|
|
||||||
if (debug) printf("Done.\n");
|
|
||||||
|
|
||||||
logTerm();
|
|
||||||
zmDbClose();
|
|
||||||
|
|
||||||
return (EXIT_SUCCESS);
|
|
||||||
}
|
|
|
@ -16,6 +16,16 @@ done
|
||||||
# See https://docs.travis-ci.com/user/cron-jobs/
|
# See https://docs.travis-ci.com/user/cron-jobs/
|
||||||
if [ "${TRAVIS_EVENT_TYPE}" == "cron" ]; then
|
if [ "${TRAVIS_EVENT_TYPE}" == "cron" ]; then
|
||||||
|
|
||||||
|
if [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
|
||||||
|
targetfolder="debian/master/mini-dinstall/incoming"
|
||||||
|
else
|
||||||
|
targetfolder="travis"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Target subfolder set to $targetfolder"
|
||||||
|
echo
|
||||||
|
|
||||||
mkdir -p ./zmrepo
|
mkdir -p ./zmrepo
|
||||||
ssh_mntchk="$(sshfs zmrepo@zmrepo.zoneminder.com:./ ./zmrepo -o workaround=rename,reconnect)"
|
ssh_mntchk="$(sshfs zmrepo@zmrepo.zoneminder.com:./ ./zmrepo -o workaround=rename,reconnect)"
|
||||||
|
|
||||||
|
@ -26,8 +36,8 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ]; then
|
||||||
echo
|
echo
|
||||||
|
|
||||||
# Don't keep packages older than 5 days
|
# Don't keep packages older than 5 days
|
||||||
find ./zmrepo -maxdepth 1 -type f -mtime +5 -delete
|
find ./zmrepo/$targetfolder/ -maxdepth 1 -type f -mtime +5 -delete
|
||||||
rsync --ignore-errors --verbose ./build/ ./zmrepo/
|
rsync -vzh --ignore-errors build/* zmrepo/$targetfolder/
|
||||||
fusermount -zu zmrepo
|
fusermount -zu zmrepo
|
||||||
else
|
else
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -18,6 +18,7 @@ if(NOT (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR))
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/api/app/Config/core.php" DESTINATION "${ZM_WEBDIR}/api/app/Config")
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/api/app/Config/core.php" DESTINATION "${ZM_WEBDIR}/api/app/Config")
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/api/app/Config/database.php" DESTINATION "${ZM_WEBDIR}/api/app/Config")
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/api/app/Config/database.php" DESTINATION "${ZM_WEBDIR}/api/app/Config")
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/api/app/Config/bootstrap.php" DESTINATION "${ZM_WEBDIR}/api/app/Config")
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/api/app/Config/bootstrap.php" DESTINATION "${ZM_WEBDIR}/api/app/Config")
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/api/lib/Cake/bootstrap.php" DESTINATION "${ZM_WEBDIR}/api/lib/Cake")
|
||||||
endif(NOT (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR))
|
endif(NOT (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR))
|
||||||
|
|
||||||
# Install the mootools symlinks (if its not in the source directory)
|
# Install the mootools symlinks (if its not in the source directory)
|
||||||
|
|
|
@ -52,7 +52,7 @@ while ( !file_exists($remSockFile) && $max_socket_tries-- ) { //sometimes we are
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !file_exists($remSockFile) ) {
|
if ( !file_exists($remSockFile) ) {
|
||||||
ajaxError("Socket $remSocketFile does not exist. This file is created by zms, and since it does not exist, either zms did not run, or zms exited early. Please check your zms logs and ensure that CGI is enabled in apache and check that the PATH_ZMS is set correctly. Make sure that ZM is actually recording. If you are trying to view a live stream and the capture process (zmc) is not running then zms will exit. Please go to http://zoneminder.readthedocs.io/en/latest/faq.html#why-can-t-i-see-streamed-images-when-i-can-see-stills-in-the-zone-window-etc for more information.");
|
ajaxError("Socket $remSockFile does not exist. This file is created by zms, and since it does not exist, either zms did not run, or zms exited early. Please check your zms logs and ensure that CGI is enabled in apache and check that the PATH_ZMS is set correctly. Make sure that ZM is actually recording. If you are trying to view a live stream and the capture process (zmc) is not running then zms will exit. Please go to http://zoneminder.readthedocs.io/en/latest/faq.html#why-can-t-i-see-streamed-images-when-i-can-see-stills-in-the-zone-window-etc for more information.");
|
||||||
} else {
|
} else {
|
||||||
if ( !@socket_sendto( $socket, $msg, strlen($msg), 0, $remSockFile ) ) {
|
if ( !@socket_sendto( $socket, $msg, strlen($msg), 0, $remSockFile ) ) {
|
||||||
ajaxError( "socket_sendto( $remSockFile ) failed: ".socket_strerror(socket_last_error()) );
|
ajaxError( "socket_sendto( $remSockFile ) failed: ".socket_strerror(socket_last_error()) );
|
||||||
|
|
|
@ -15,4 +15,4 @@ configure_file(app/Config/core.php.default "${CMAKE_CURRENT_BINARY_DIR}/app/Conf
|
||||||
configure_file(app/Config/bootstrap.php.in "${CMAKE_CURRENT_BINARY_DIR}/app/Config/bootstrap.php" @ONLY)
|
configure_file(app/Config/bootstrap.php.in "${CMAKE_CURRENT_BINARY_DIR}/app/Config/bootstrap.php" @ONLY)
|
||||||
|
|
||||||
# Configure lib/Cake/bootstrap.php
|
# Configure lib/Cake/bootstrap.php
|
||||||
configure_file(lib/Cake/bootstrap.php.in "${CMAKE_CURRENT_BINARY_DIR}/lib/Cake//bootstrap.php" @ONLY)
|
configure_file(lib/Cake/bootstrap.php.in "${CMAKE_CURRENT_BINARY_DIR}/lib/Cake/bootstrap.php" @ONLY)
|
||||||
|
|
|
@ -88,7 +88,7 @@ class DATABASE_CONFIG {
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
if (strpos(ZM_DB_HOST, ':')):
|
if (strpos(ZM_DB_HOST, ':')):
|
||||||
$array = explode(':', ZM_DB_HOST, 2);
|
$array = explode(':', ZM_DB_HOST, 2);
|
||||||
if (is_numeric($array[1])):
|
if (ctype_digit($array[1])):
|
||||||
$this->default['host'] = $array[0];
|
$this->default['host'] = $array[0];
|
||||||
$this->default['port'] = $array[1];
|
$this->default['port'] = $array[1];
|
||||||
else:
|
else:
|
||||||
|
|
Before Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 384 B |
Before Width: | Height: | Size: 61 B |
After Width: | Height: | Size: 137 B |
|
@ -1,51 +1,81 @@
|
||||||
<?php
|
<?php
|
||||||
require_once( 'database.php' );
|
require_once( 'database.php' );
|
||||||
class Storage {
|
class Storage {
|
||||||
public function __construct( $IdOrRow = NULL ) {
|
public function __construct( $IdOrRow = NULL ) {
|
||||||
$row = NULL;
|
$row = NULL;
|
||||||
if ( $IdOrRow ) {
|
if ( $IdOrRow ) {
|
||||||
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
|
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
|
||||||
$row = dbFetchOne( 'SELECT * FROM Storage WHERE Id=?', NULL, array( $IdOrRow ) );
|
$row = dbFetchOne( 'SELECT * FROM Storage WHERE Id=?', NULL, array( $IdOrRow ) );
|
||||||
if ( ! $row ) {
|
if ( ! $row ) {
|
||||||
Error("Unable to load Storage record for Id=" . $IdOrRow );
|
Error("Unable to load Storage record for Id=" . $IdOrRow );
|
||||||
}
|
}
|
||||||
} elseif ( is_array( $IdOrRow ) ) {
|
} elseif ( is_array( $IdOrRow ) ) {
|
||||||
$row = $IdOrRow;
|
$row = $IdOrRow;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if ( $row ) {
|
|
||||||
foreach ($row as $k => $v) {
|
|
||||||
$this->{$k} = $v;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->{'Name'} = '';
|
|
||||||
$this->{'Path'} = '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if ( $row ) {
|
||||||
|
foreach ($row as $k => $v) {
|
||||||
|
$this->{$k} = $v;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->{'Name'} = '';
|
||||||
|
$this->{'Path'} = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function Path() {
|
public function Path() {
|
||||||
if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) {
|
if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) {
|
||||||
return $this->{'Path'};
|
return $this->{'Path'};
|
||||||
} else if ( ! isset($this->{'Id'}) ) {
|
} else if ( ! isset($this->{'Id'}) ) {
|
||||||
return ZM_DIR_EVENTS;
|
$path = ZM_DIR_EVENTS;
|
||||||
}
|
if ( $path[0] != '/' ) {
|
||||||
return $this->{'Name'};
|
$this->{'Path'} = ZM_PATH_WEB.'/'.ZM_DIR_EVENTS;
|
||||||
}
|
} else {
|
||||||
public function __call( $fn, array $args= NULL){
|
$this->{'Path'} = ZM_DIR_EVENTS;
|
||||||
if(isset($this->{$fn})){
|
}
|
||||||
return $this->{$fn};
|
return $this->{'Path'};
|
||||||
#array_unshift($args, $this);
|
|
||||||
#call_user_func_array( $this->{$fn}, $args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public static function find_all() {
|
return $this->{'Name'};
|
||||||
$storage_areas = array();
|
}
|
||||||
$result = dbQuery( 'SELECT * FROM Storage ORDER BY Name');
|
public function Name() {
|
||||||
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' );
|
if ( isset( $this->{'Name'} ) and ( $this->{'Name'} != '' ) ) {
|
||||||
foreach ( $results as $row => $obj ) {
|
return $this->{'Name'};
|
||||||
$storage_areas[] = $obj;
|
} else if ( ! isset($this->{'Id'}) ) {
|
||||||
}
|
return 'Default';
|
||||||
return $storage_areas;
|
|
||||||
}
|
}
|
||||||
|
return $this->{'Name'};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __call( $fn, array $args= NULL){
|
||||||
|
if(isset($this->{$fn})){
|
||||||
|
return $this->{$fn};
|
||||||
|
#array_unshift($args, $this);
|
||||||
|
#call_user_func_array( $this->{$fn}, $args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static function find_all() {
|
||||||
|
$storage_areas = array();
|
||||||
|
$result = dbQuery( 'SELECT * FROM Storage ORDER BY Name');
|
||||||
|
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' );
|
||||||
|
foreach ( $results as $row => $obj ) {
|
||||||
|
$storage_areas[] = $obj;
|
||||||
|
}
|
||||||
|
return $storage_areas;
|
||||||
|
}
|
||||||
|
public function disk_usage_percent() {
|
||||||
|
$path = $this->Path();
|
||||||
|
$total = disk_total_space( $path );
|
||||||
|
if ( ! $total ) {
|
||||||
|
Error("disk_total_space returned false for " . $path );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
$free = disk_free_space( $path );
|
||||||
|
if ( ! $free ) {
|
||||||
|
Error("disk_free_space returned false for " . $path );
|
||||||
|
}
|
||||||
|
$usage = round(($total - $free) / $total * 100);
|
||||||
|
return $usage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -33,7 +33,7 @@ function dbConnect()
|
||||||
if (strpos(ZM_DB_HOST, ':')) {
|
if (strpos(ZM_DB_HOST, ':')) {
|
||||||
// Host variable may carry a port or socket.
|
// Host variable may carry a port or socket.
|
||||||
list($host, $portOrSocket) = explode(':', ZM_DB_HOST, 2);
|
list($host, $portOrSocket) = explode(':', ZM_DB_HOST, 2);
|
||||||
if (is_numeric($portOrSocket)) {
|
if (ctype_digit($portOrSocket)) {
|
||||||
$socket = ':host='.$host . ';port='.$portOrSocket;
|
$socket = ':host='.$host . ';port='.$portOrSocket;
|
||||||
} else {
|
} else {
|
||||||
$socket = ':unix_socket='.$portOrSocket;
|
$socket = ':unix_socket='.$portOrSocket;
|
||||||
|
|
|
@ -875,21 +875,12 @@ function zmaControl( $monitor, $mode=false ) {
|
||||||
daemonControl( "stop", "zmtrack.pl", "-m ".$monitor['Id'] );
|
daemonControl( "stop", "zmtrack.pl", "-m ".$monitor['Id'] );
|
||||||
}
|
}
|
||||||
daemonControl( "stop", "zma", "-m ".$monitor['Id'] );
|
daemonControl( "stop", "zma", "-m ".$monitor['Id'] );
|
||||||
if ( ZM_OPT_FRAME_SERVER ) {
|
|
||||||
daemonControl( "stop", "zmf", "-m ".$monitor['Id'] );
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if ( $mode == "restart" ) {
|
if ( $mode == "restart" ) {
|
||||||
if ( ZM_OPT_CONTROL ) {
|
if ( ZM_OPT_CONTROL ) {
|
||||||
daemonControl( "stop", "zmtrack.pl", "-m ".$monitor['Id'] );
|
daemonControl( "stop", "zmtrack.pl", "-m ".$monitor['Id'] );
|
||||||
}
|
}
|
||||||
daemonControl( "stop", "zma", "-m ".$monitor['Id'] );
|
daemonControl( "stop", "zma", "-m ".$monitor['Id'] );
|
||||||
if ( ZM_OPT_FRAME_SERVER ) {
|
|
||||||
daemonControl( "stop", "zmf", "-m ".$monitor['Id'] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( ZM_OPT_FRAME_SERVER ) {
|
|
||||||
daemonControl( "start", "zmf", "-m ".$monitor['Id'] );
|
|
||||||
}
|
}
|
||||||
daemonControl( "start", "zma", "-m ".$monitor['Id'] );
|
daemonControl( "start", "zma", "-m ".$monitor['Id'] );
|
||||||
if ( ZM_OPT_CONTROL && $monitor['Controllable'] && $monitor['TrackMotion'] && ( $monitor['Function'] == 'Modect' || $monitor['Function'] == 'Mocord' ) ) {
|
if ( ZM_OPT_CONTROL && $monitor['Controllable'] && $monitor['TrackMotion'] && ( $monitor['Function'] == 'Modect' || $monitor['Function'] == 'Mocord' ) ) {
|
||||||
|
|
|
@ -105,6 +105,7 @@ if ( ! in_array( $css, $css_skins ) ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
define( "ZM_BASE_PATH", dirname( $_SERVER['REQUEST_URI'] ) );
|
define( "ZM_BASE_PATH", dirname( $_SERVER['REQUEST_URI'] ) );
|
||||||
|
define( "ZM_SKIN_NAME", $skin );
|
||||||
define( "ZM_SKIN_PATH", "skins/$skin" );
|
define( "ZM_SKIN_PATH", "skins/$skin" );
|
||||||
|
|
||||||
$skinBase = array(); // To allow for inheritance of skins
|
$skinBase = array(); // To allow for inheritance of skins
|
||||||
|
|
|
@ -822,14 +822,6 @@ $OLANG = array(
|
||||||
'Prompt' => "Crează imagini analizate cu marcaje ale mişcării",
|
'Prompt' => "Crează imagini analizate cu marcaje ale mişcării",
|
||||||
'Help' => "Implicit, în cazul unei alarme, ZoneMinder înregistrează atât imaginile neprelucrate cât şi cele ce au fost analizate şi au zone marcate unde a fost detectată mişcare. Acest lucru poate fi foarte folositor la configurarea zonelor sau în analiza evenimentelor. Acest parametru permite oprirea înregistrării imaginilor cu zone de mişcare marcate."
|
'Help' => "Implicit, în cazul unei alarme, ZoneMinder înregistrează atât imaginile neprelucrate cât şi cele ce au fost analizate şi au zone marcate unde a fost detectată mişcare. Acest lucru poate fi foarte folositor la configurarea zonelor sau în analiza evenimentelor. Acest parametru permite oprirea înregistrării imaginilor cu zone de mişcare marcate."
|
||||||
),
|
),
|
||||||
'OPT_FRAME_SERVER' => array(
|
|
||||||
'Prompt' => "Daemon-ul de analiză va scrie imaginile pe disc",
|
|
||||||
'Help' => "În unele cazuri este posibil ca viteza de scriere a unui HDD sa fie atât de mică încat să cauzeze încetinirea daemon-ului de analiză în special în timpul evenimentelor cu multe cadre. Activarea acestei opţiuni porneşte daemon-ul de cadre (zmf) care va 'primi' imaginile de la daemon-ul de analiză şi le va scrie pe disc. Dacă această transmisie eşuează sau apar alte erori, funcţia de scriere va reveni daemon-ului de analiză."
|
|
||||||
),
|
|
||||||
'FRAME_SOCKET_SIZE' => array(
|
|
||||||
'Prompt' => "Specificaţi dimensiunea memoriei tampon",
|
|
||||||
'Help' => "Pentru imaginile de dimensiuni mari capturate este posibil ca scrierea lor pe disc să eşueze deoarece cantitatea de informaţie scrisă este mai mare decât memoria tampon alocată. Deşi imaginile sunt scrise apoi de către daemon-ul de analiză, se distruge obiectul daemon-ului de cadre. Puteţi folosi această opţiune pentru a specifica o memorie tampon de dimensiuni mai mari. Va trebui sa modificaţi dimensiunea socket-ului tampon maxim folosind 'sysctl' (sau in /proc/sys/net/core/wmem_max) pentru a permite setarea acestei noi valori. Alternativa este să schimbaţi mărimea implicită a memorie tampon a sistemului, caz în care modificarea acestei valori nu mai este necesară."
|
|
||||||
),
|
|
||||||
'OPT_CONTROL' => array(
|
'OPT_CONTROL' => array(
|
||||||
'Prompt' => "Suport camere controlabile (rotire/înclinare/zoom)",
|
'Prompt' => "Suport camere controlabile (rotire/înclinare/zoom)",
|
||||||
'Help' => "ZoneMinder include suport limitat pentru camere controlabile. Sunt incluse câteva protocoale mostră şi pot fi adăugate cu uşurinţă şi altele. Dacă vreţi să controlaţi camerele prin intermediul ZoneMinder selectaţi această opţiune."
|
'Help' => "ZoneMinder include suport limitat pentru camere controlabile. Sunt incluse câteva protocoale mostră şi pot fi adăugate cu uşurinţă şi altele. Dacă vreţi să controlaţi camerele prin intermediul ZoneMinder selectaţi această opţiune."
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#scaleControl {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
#controls {
|
#controls {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#scaleControl {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
#controls {
|
#controls {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
#scaleControl {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
#controls {
|
#controls {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
Before Width: | Height: | Size: 293 B |
After Width: | Height: | Size: 313 B |
Before Width: | Height: | Size: 232 B |
After Width: | Height: | Size: 321 B |
Before Width: | Height: | Size: 263 B |
After Width: | Height: | Size: 324 B |
Before Width: | Height: | Size: 538 B |
After Width: | Height: | Size: 520 B |
Before Width: | Height: | Size: 524 B |
After Width: | Height: | Size: 479 B |
Before Width: | Height: | Size: 284 B |
After Width: | Height: | Size: 304 B |
Before Width: | Height: | Size: 265 B |
After Width: | Height: | Size: 299 B |
Before Width: | Height: | Size: 206 B |
After Width: | Height: | Size: 237 B |
Before Width: | Height: | Size: 203 B |
After Width: | Height: | Size: 234 B |
Before Width: | Height: | Size: 278 B |
After Width: | Height: | Size: 297 B |
Before Width: | Height: | Size: 286 B |
After Width: | Height: | Size: 332 B |
Before Width: | Height: | Size: 282 B |
After Width: | Height: | Size: 337 B |
Before Width: | Height: | Size: 621 B |
After Width: | Height: | Size: 641 B |
Before Width: | Height: | Size: 76 B |
After Width: | Height: | Size: 156 B |
Before Width: | Height: | Size: 76 B |
After Width: | Height: | Size: 156 B |
Before Width: | Height: | Size: 76 B |
After Width: | Height: | Size: 156 B |
Before Width: | Height: | Size: 68 B |
After Width: | Height: | Size: 165 B |
Before Width: | Height: | Size: 68 B |
After Width: | Height: | Size: 162 B |
|
@ -27,7 +27,7 @@ function exportHeader( $title )
|
||||||
<title><?php echo $title ?></title>
|
<title><?php echo $title ?></title>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
<!--
|
<!--
|
||||||
<?php include( ZM_SKIN_PATH.'/css/export.css' ); ?>
|
<?php include( ZM_SKIN_PATH.'/css/'.ZM_SKIN_NAME.'/export.css' ); ?>
|
||||||
|
|
||||||
|
|
||||||
ul.tabs {
|
ul.tabs {
|
||||||
|
|
|
@ -18,8 +18,7 @@
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
//
|
//
|
||||||
|
|
||||||
if ( !canView( 'Events' ) )
|
if ( !canView( 'Events' ) ) {
|
||||||
{
|
|
||||||
$view = "error";
|
$view = "error";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -30,19 +29,19 @@ $eid = validInt($_REQUEST['eid']);
|
||||||
if ( !empty($_REQUEST['fid']) )
|
if ( !empty($_REQUEST['fid']) )
|
||||||
$fid = validInt($_REQUEST['fid']);
|
$fid = validInt($_REQUEST['fid']);
|
||||||
|
|
||||||
$sql = 'SELECT E.*,M.Name AS MonitorName,M.DefaultScale FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE E.Id = ?';
|
$Event = new Event( $eid );
|
||||||
$event = dbFetchOne( $sql, NULL, array($eid) );
|
$Monitor = $Event->Monitor();
|
||||||
|
|
||||||
if ( !empty($fid) ) {
|
if ( !empty($fid) ) {
|
||||||
$sql = 'SELECT * FROM Frames WHERE EventId = ? AND FrameId = ?';
|
$sql = 'SELECT * FROM Frames WHERE EventId = ? AND FrameId = ?';
|
||||||
if ( !($frame = dbFetchOne( $sql, NULL, array($eid, $fid) )) )
|
if ( !($frame = dbFetchOne( $sql, NULL, array($eid, $fid) )) )
|
||||||
$frame = array( 'FrameId'=>$fid, 'Type'=>'Normal', 'Score'=>0 );
|
$frame = array( 'FrameId'=>$fid, 'Type'=>'Normal', 'Score'=>0 );
|
||||||
} else {
|
} else {
|
||||||
$frame = dbFetchOne( 'SELECT * FROM Frames WHERE EventId = ? AND Score = ?', NULL, array( $eid, $event['MaxScore'] ) );
|
$frame = dbFetchOne( 'SELECT * FROM Frames WHERE EventId = ? AND Score = ?', NULL, array( $eid, $Event->MaxScore() ) );
|
||||||
}
|
}
|
||||||
$Frame = new Frame( $frame );
|
$Frame = new Frame( $frame );
|
||||||
|
|
||||||
$maxFid = $event['Frames'];
|
$maxFid = $Event->Frames();
|
||||||
|
|
||||||
$firstFid = 1;
|
$firstFid = 1;
|
||||||
$prevFid = $Frame->FrameId()-1;
|
$prevFid = $Frame->FrameId()-1;
|
||||||
|
@ -51,12 +50,17 @@ $lastFid = $maxFid;
|
||||||
|
|
||||||
$alarmFrame = $Frame->Type()=='Alarm';
|
$alarmFrame = $Frame->Type()=='Alarm';
|
||||||
|
|
||||||
if ( isset( $_REQUEST['scale'] ) )
|
if ( isset( $_REQUEST['scale'] ) ) {
|
||||||
$scale = validInt($_REQUEST['scale']);
|
$scale = validInt($_REQUEST['scale']);
|
||||||
else
|
} else if ( isset( $_COOKIE['zmWatchScale'.$Monitor->Id()] ) ) {
|
||||||
$scale = max( reScale( SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
|
$scale = $_COOKIE['zmWatchScale'.$Monitor->Id()];
|
||||||
|
} else if ( isset( $_COOKIE['zmWatchScale'] ) ) {
|
||||||
|
$scale = $_COOKIE['zmWatchScale'];
|
||||||
|
} else {
|
||||||
|
$scale = max( reScale( SCALE_BASE, $Monitor->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
|
||||||
|
}
|
||||||
|
|
||||||
$imageData = getImageSrc( $event, $frame, $scale, (isset($_REQUEST['show']) && $_REQUEST['show']=="capt") );
|
$imageData = $Event->getImageSrc( $frame, $scale, (isset($_REQUEST['show']) && $_REQUEST['show']=="capt") );
|
||||||
|
|
||||||
$imagePath = $imageData['thumbPath'];
|
$imagePath = $imageData['thumbPath'];
|
||||||
$eventPath = $imageData['eventPath'];
|
$eventPath = $imageData['eventPath'];
|
||||||
|
@ -65,43 +69,48 @@ $rImagePath = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-diag-r.jpg", $eventPath,
|
||||||
|
|
||||||
$focusWindow = true;
|
$focusWindow = true;
|
||||||
|
|
||||||
xhtmlHeaders(__FILE__, translate('Frame')." - ".$event['Id']." - ".$Frame->FrameId() );
|
xhtmlHeaders(__FILE__, translate('Frame')." - ".$Event->Id()." - ".$Frame->FrameId() );
|
||||||
?>
|
?>
|
||||||
<body>
|
<body>
|
||||||
<div id="page">
|
<div id="page">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
|
<form>
|
||||||
<div id="headerButtons">
|
<div id="headerButtons">
|
||||||
<?php if ( ZM_RECORD_EVENT_STATS && $alarmFrame ) { echo makePopupLink( '?view=stats&eid='.$event['Id'].'&fid='.$Frame->FrameId(), 'zmStats', 'stats', translate('Stats') ); } ?>
|
<?php if ( ZM_RECORD_EVENT_STATS && $alarmFrame ) { echo makePopupLink( '?view=stats&eid='.$Event->Id().'&fid='.$Frame->FrameId(), 'zmStats', 'stats', translate('Stats') ); } ?>
|
||||||
<?php if ( canEdit( 'Events' ) ) { ?><a href="?view=none&action=delete&markEid=<?php echo $event['Id'] ?>"><?php echo translate('Delete') ?></a><?php } ?>
|
<?php if ( canEdit( 'Events' ) ) { ?><a href="?view=none&action=delete&markEid=<?php echo $Event->Id() ?>"><?php echo translate('Delete') ?></a><?php } ?>
|
||||||
<a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a>
|
<a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a>
|
||||||
</div>
|
</div>
|
||||||
<h2><?php echo translate('Frame') ?> <?php echo $event['Id']."-".$Frame->FrameId()." (".$Frame->Score().")" ?></h2>
|
<div id="scaleControl"><label for="scale"><?php echo translate('Scale') ?></label><?php echo buildSelect( "scale", $scales, "changeScale();" ); ?></div>
|
||||||
|
<h2><?php echo translate('Frame') ?> <?php echo $Event->Id()."-".$Frame->FrameId()." (".$Frame->Score().")" ?></h2>
|
||||||
|
<input type="hidden" name="base_width" id="base_width" value="<?php echo $Event->Width(); ?>"/>
|
||||||
|
<input type="hidden" name="base_height" id="base_height" value="<?php echo $Event->Height(); ?>"/>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<p id="image">
|
<p id="image">
|
||||||
<?php if ( $imageData['hasAnalImage'] ) { ?>
|
<?php if ( $imageData['hasAnalImage'] ) { ?>
|
||||||
<a href="?view=frame&eid=<?php echo $event['Id'] ?>&fid=<?php echo $Frame->FrameId() ?>&scale=<?php echo $scale ?>&show=<?php echo $imageData['isAnalImage']?"capt":"anal" ?>">
|
<a href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $Frame->FrameId() ?>&scale=<?php echo $scale ?>&show=<?php echo $imageData['isAnalImage']?"capt":"anal" ?>">
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<img src="<?php echo $Frame->getImageSrc($imageData['isAnalImage']?'analyse':'capture') ?>" width="<?php echo reScale( $event['Width'], $event['DefaultScale'], $scale ) ?>" height="<?php echo reScale( $event['Height'], $event['DefaultScale'], $scale ) ?>" alt="<?php echo $Frame->EventId()."-".$Frame->FrameId() ?>" class="<?php echo $imageData['imageClass'] ?>"/>
|
<img id="frameImg" src="<?php echo $Frame->getImageSrc($imageData['isAnalImage']?'analyse':'capture') ?>" width="<?php echo reScale( $Event->Width(), $Event->DefaultScale(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $Event->DefaultScale(), $scale ) ?>" alt="<?php echo $Frame->EventId()."-".$Frame->FrameId() ?>" class="<?php echo $imageData['imageClass'] ?>"/>
|
||||||
<?php if ( $imageData['hasAnalImage'] ) { ?></a><?php } ?>
|
<?php if ( $imageData['hasAnalImage'] ) { ?></a><?php } ?>
|
||||||
|
|
||||||
<p id="controls">
|
<p id="controls">
|
||||||
<?php if ( $Frame->FrameId() > 1 ) { ?>
|
<?php if ( $Frame->FrameId() > 1 ) { ?>
|
||||||
<a id="firstLink" href="?view=frame&eid=<?php echo $event['Id'] ?>&fid=<?php echo $firstFid ?>&scale=<?php echo $scale ?>"><?php echo translate('First') ?></a>
|
<a id="firstLink" href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $firstFid ?>&scale=<?php echo $scale ?>"><?php echo translate('First') ?></a>
|
||||||
<?php } if ( $Frame->FrameId() > 1 ) { ?>
|
<?php } if ( $Frame->FrameId() > 1 ) { ?>
|
||||||
<a id="prevLink" href="?view=frame&eid=<?php echo $event['Id'] ?>&fid=<?php echo $prevFid ?>&scale=<?php echo $scale ?>"><?php echo translate('Prev') ?></a>
|
<a id="prevLink" href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $prevFid ?>&scale=<?php echo $scale ?>"><?php echo translate('Prev') ?></a>
|
||||||
<?php } if ( $Frame->FrameId() < $maxFid ) { ?>
|
<?php } if ( $Frame->FrameId() < $maxFid ) { ?>
|
||||||
<a id="nextLink" href="?view=frame&eid=<?php echo $event['Id'] ?>&fid=<?php echo $nextFid ?>&scale=<?php echo $scale ?>"><?php echo translate('Next') ?></a>
|
<a id="nextLink" href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $nextFid ?>&scale=<?php echo $scale ?>"><?php echo translate('Next') ?></a>
|
||||||
<?php } if ( $Frame->FrameId() < $maxFid ) { ?>
|
<?php } if ( $Frame->FrameId() < $maxFid ) { ?>
|
||||||
<a id="lastLink" href="?view=frame&eid=<?php echo $event['Id'] ?>&fid=<?php echo $lastFid ?>&scale=<?php echo $scale ?>"><?php echo translate('Last') ?></a>
|
<a id="lastLink" href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $lastFid ?>&scale=<?php echo $scale ?>"><?php echo translate('Last') ?></a>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</p>
|
</p>
|
||||||
<?php if (file_exists ($dImagePath)) { ?>
|
<?php if (file_exists ($dImagePath)) { ?>
|
||||||
<p id="diagImagePath"><?php echo $dImagePath ?></p>
|
<p id="diagImagePath"><?php echo $dImagePath ?></p>
|
||||||
<p id="diagImage"><img src=?"<?php echo viewImagePath( $dImagePath ) ?>" width="<?php echo reScale( $event['Width'], $event['DefaultScale'], $scale ) ?>" height="<?php echo reScale( $event['Height'], $event['DefaultScale'], $scale ) ?>" class="<?php echo $imageData['imageClass'] ?>"/></p>
|
<p id="diagImage"><img src=?"<?php echo viewImagePath( $dImagePath ) ?>" width="<?php echo reScale( $Event->Width(), $Event->DefaultScale(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $Event->DefaultScale(), $scale ) ?>" class="<?php echo $imageData['imageClass'] ?>"/></p>
|
||||||
<?php } if (file_exists ($rImagePath)) { ?>
|
<?php } if (file_exists ($rImagePath)) { ?>
|
||||||
<p id="refImagePath"><?php echo $rImagePath ?></p>
|
<p id="refImagePath"><?php echo $rImagePath ?></p>
|
||||||
<p id="refImage"><img src="<?php echo viewImagePath( $rImagePath ) ?>" width="<?php echo reScale( $event['Width'], $event['DefaultScale'], $scale ) ?>" height="<?php echo reScale( $event['Height'], $event['DefaultScale'], $scale ) ?>" class="<?php echo $imageData['imageClass'] ?>"/></p>
|
<p id="refImage"><img src="<?php echo viewImagePath( $rImagePath ) ?>" width="<?php echo reScale( $Event->Width(), $Event->DefaultScale(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $Event->DefaultScale(), $scale ) ?>" class="<?php echo $imageData['imageClass'] ?>"/></p>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
function changeScale() {
|
||||||
|
var scale = $('scale').get('value');
|
||||||
|
var img = $('frameImg');
|
||||||
|
if ( img ) {
|
||||||
|
var baseWidth = $('base_width').value;
|
||||||
|
var baseHeight = $('base_height').value;
|
||||||
|
var newWidth = ( baseWidth * scale ) / SCALE_BASE;
|
||||||
|
var newHeight = ( baseHeight * scale ) / SCALE_BASE;
|
||||||
|
|
||||||
|
img.style.width = newWidth + "px";
|
||||||
|
img.style.height = newHeight + "px";
|
||||||
|
}
|
||||||
|
Cookie.write( 'zmWatchScale', scale, { duration: 10*365 } );
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
var SCALE_BASE = <?php echo SCALE_BASE ?>;
|
|
@ -34,7 +34,8 @@ ZM_WEB_GROUP=@WEB_GROUP@
|
||||||
# ZoneMinder database type: so far only mysql is supported
|
# ZoneMinder database type: so far only mysql is supported
|
||||||
ZM_DB_TYPE=@ZM_DB_TYPE@
|
ZM_DB_TYPE=@ZM_DB_TYPE@
|
||||||
|
|
||||||
# ZoneMinder database hostname or ip address
|
# ZoneMinder database hostname or ip address and optionally port or unix socket
|
||||||
|
# Acceptable formats include hostname[:port], ip_address[:port], or localhost:unix_socket
|
||||||
ZM_DB_HOST=@ZM_DB_HOST@
|
ZM_DB_HOST=@ZM_DB_HOST@
|
||||||
|
|
||||||
# ZoneMinder database name
|
# ZoneMinder database name
|
||||||
|
|