Merge branch 'release-1.34' of github.com:ZoneMinder/zoneminder into release-1.34
This commit is contained in:
commit
17369e73e2
|
@ -1,10 +1,10 @@
|
|||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
daysUntilStale: 180
|
||||
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
daysUntilClose: 30
|
||||
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
|
|
|
@ -875,7 +875,6 @@ configure_file(zmlinkcontent.sh.in "${CMAKE_CURRENT_BINARY_DIR}/zmlinkcontent.sh
|
|||
|
||||
# Create a target for man pages
|
||||
include(Pod2Man)
|
||||
ADD_MANPAGE_TARGET()
|
||||
|
||||
# Process subdirectories
|
||||
|
||||
|
|
|
@ -53,8 +53,7 @@ MACRO(POD2MAN PODFILE MANFILE SECTION MANPAGE_DEST_PREFIX)
|
|||
|
||||
SET(MANPAGE_TARGET "man-${MANFILE}")
|
||||
|
||||
ADD_CUSTOM_TARGET(${MANPAGE_TARGET} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz)
|
||||
ADD_DEPENDENCIES(man ${MANPAGE_TARGET})
|
||||
ADD_CUSTOM_TARGET(${MANPAGE_TARGET} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz)
|
||||
|
||||
INSTALL(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz
|
||||
|
|
|
@ -46,3 +46,6 @@ ZM_PATH_SWAP=@ZM_TMPDIR@
|
|||
# Full path to optional arp binary
|
||||
# ZoneMinder will find the arp binary automatically on most systems
|
||||
ZM_PATH_ARP="@ZM_PATH_ARP@"
|
||||
|
||||
#Full path to shutdown binary
|
||||
ZM_PATH_SHUTDOWN="@ZM_PATH_SHUTDOWN@"
|
||||
|
|
|
@ -476,7 +476,7 @@ CREATE TABLE `Monitors` (
|
|||
`Hue` mediumint(7) NOT NULL default '-1',
|
||||
`Colour` mediumint(7) NOT NULL default '-1',
|
||||
`EventPrefix` varchar(32) NOT NULL default 'Event-',
|
||||
`LabelFormat` varchar(64) default '%N - %y/%m/%d %H:%M:%S',
|
||||
`LabelFormat` varchar(64),
|
||||
`LabelX` smallint(5) unsigned NOT NULL default '0',
|
||||
`LabelY` smallint(5) unsigned NOT NULL default '0',
|
||||
`LabelSize` smallint(5) unsigned NOT NULL DEFAULT '1',
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
/* This was done in 1.31.0 but zm_create.sql.in wasn't updated to match. */
|
||||
ALTER TABLE Monitors MODIFY LinkedMonitors varchar(255);
|
|
@ -0,0 +1,10 @@
|
|||
zoneminder (1.28.1-1) unstable; urgency=low
|
||||
|
||||
This version is no longer automatically initialize or upgrade database.
|
||||
See README.Debian for details.
|
||||
|
||||
Changed installation paths (please correct your web server configuration):
|
||||
/usr/share/zoneminder --> /usr/share/zoneminder/www
|
||||
/usr/lib/cgi-bin --> /usr/lib/zoneminder/cgi-bin
|
||||
|
||||
-- Dmitry Smirnov <onlyjob@debian.org> Tue, 31 Mar 2015 15:12:17 +1100
|
|
@ -0,0 +1,130 @@
|
|||
Zoneminder for Debian
|
||||
---------------------
|
||||
|
||||
Initializing database
|
||||
---------------------
|
||||
|
||||
pv /usr/share/zoneminder/db/zm_create.sql | sudo mysql --defaults-file=/etc/mysql/debian.cnf
|
||||
OR
|
||||
cat /usr/share/zoneminder/db/zm_create.sql | sudo mysql --defaults-file=/etc/mysql/debian.cnf
|
||||
|
||||
echo 'grant lock tables,alter,create,index,select,insert,update,delete on zm.* to 'zmuser'@localhost identified by "zmpass";'\
|
||||
| sudo mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
|
||||
Hint: generate secure password with `pwgen` and update "/etc/zm/zm.conf"
|
||||
accordingly.
|
||||
|
||||
The following command can help to ensure that zoneminder can read its
|
||||
configuration file:
|
||||
|
||||
chgrp -c www-data /etc/zm/zm.conf
|
||||
|
||||
|
||||
Upgrading database
|
||||
------------------
|
||||
|
||||
The database is updated automatically on installation. You should not need to take this step.
|
||||
|
||||
Assuming that database is on "localhost" then the following command can be
|
||||
used to upgrade "zm" database:
|
||||
|
||||
zmupdate.pl
|
||||
|
||||
Additional permissions may be required to perform upgrade:
|
||||
|
||||
echo 'grant lock tables, create, alter on zm.* to 'zmuser'@localhost identified by "zmpass";'\
|
||||
| sudo mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
|
||||
The following command prints the current version of zoneminder database:
|
||||
|
||||
echo 'select Value from Config where Name = "ZM_DYN_CURR_VERSION";' \
|
||||
| sudo mysql --defaults-file=/etc/mysql/debian.cnf --skip-column-names zm
|
||||
|
||||
|
||||
Enabling service
|
||||
----------------
|
||||
|
||||
By default Zoneminder service is not automatically started and needs to be
|
||||
manually enabled once database is configured:
|
||||
|
||||
sudo systemctl enable zoneminder.service
|
||||
|
||||
|
||||
Web server set-up
|
||||
-----------------
|
||||
|
||||
There are few manual steps to get the web interface working:
|
||||
|
||||
## Apache2
|
||||
|
||||
Apache can be configured as folder "/zm" using sample .conf:
|
||||
|
||||
sudo a2enconf zoneminder
|
||||
|
||||
Alternatively Apache web site configuration template can be used to setup
|
||||
zoneminder as "http://zoneminder":
|
||||
|
||||
sudo cp -v /usr/share/doc/zoneminder/examples/apache.conf /etc/apache2/sites-available/
|
||||
sudo a2ensite zoneminder.conf
|
||||
|
||||
Common configuration steps for Apache2:
|
||||
|
||||
sudo a2enmod cgi
|
||||
sudo service apache2 reload
|
||||
|
||||
|
||||
## nginx / fcgiwrap
|
||||
|
||||
Nginx needs "php-fpm" package to support PHP and "fcgiwrap" package
|
||||
for binary "cgi-bin" applications:
|
||||
|
||||
sudo apt-get install php-fpm fcgiwrap
|
||||
|
||||
To enable a URL alias that makes Zoneminder available from
|
||||
|
||||
http://yourserver/zm
|
||||
|
||||
the following line is to be added to "server" section of a web site
|
||||
configuration:
|
||||
|
||||
include /usr/share/doc/zoneminder/examples/nginx.conf;
|
||||
|
||||
For "default" web site it would be sufficient to include the above
|
||||
statement to the file
|
||||
|
||||
/etc/nginx/sites-enabled/default
|
||||
|
||||
To avoid problems with feeds from multiple cameras "fcgiwrap" should be
|
||||
configured to start at least as many processes as there are cameras.
|
||||
It can be done by adjusting DAEMON_OPTS in "/etc/default/fcgiwrap".
|
||||
Systemd users may be affected by the following bug:
|
||||
|
||||
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=792705
|
||||
|
||||
|
||||
## Note:
|
||||
|
||||
When Zoneminder web site is running it may be necessary to set
|
||||
Options/Paths/PATH_ZMS to "/zm/cgi-bin/nph-zms" or according to chosen web
|
||||
site configuration.
|
||||
|
||||
|
||||
Changing the location for images and events
|
||||
-------------------------------------------
|
||||
|
||||
ZoneMinder is now able to be configured to use an alternative location for storing
|
||||
events and images at compile time. This package makes use of that, so symlinks in
|
||||
/usr/share/zoneminder/www are no longer necessary.
|
||||
|
||||
Access to /dev/video*
|
||||
---------------------
|
||||
|
||||
For cameras which require access to /dev/video*, zoneminder may need the
|
||||
www-data user added to the video group in order to see those cameras:
|
||||
|
||||
adduser www-data video
|
||||
|
||||
Note that all web applications running on the zoneminder server will then have
|
||||
access to all video devices on the system.
|
||||
|
||||
-- Vagrant Cascadian <vagrant@debian.org> Sun, 27 Mar 2011 13:06:56 -0700
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
## Separate substantial /usr/share into its own arch-all package.
|
||||
|
||||
## Decide how to handle database updates.
|
||||
|
||||
* Consider possibility that database may be on another machine (#469239).
|
||||
* Consider dbconfig-common? Probably not (what if database is not on localhost?).
|
||||
|
||||
### Run `zmupdate.pl` from service control scripts (init.d, service) on start?
|
||||
|
||||
Automatic upgrade will break "one DB, many zoneminders" setup (unimportant?).
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
zoneminder (1.31.39~20180223.27-stretch-1) unstable; urgency=low
|
||||
*
|
||||
-- Isaac Connor <iconnor@connortechnology.com> Fri, 23 Feb 2018 14:15:59 -0500
|
|
@ -0,0 +1,3 @@
|
|||
.gitattributes
|
||||
web/api/.gitattributes
|
||||
web/api/.gitignore
|
|
@ -0,0 +1 @@
|
|||
9
|
|
@ -0,0 +1,57 @@
|
|||
# Remember to enable cgi mod (i.e. "a2enmod cgi").
|
||||
ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin"
|
||||
<Directory "/usr/lib/zoneminder/cgi-bin">
|
||||
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
|
||||
# Order matters. This alias must come first.
|
||||
Alias /zm/cache /var/cache/zoneminder/cache
|
||||
<Directory /var/cache/zoneminder/cache>
|
||||
Options -Indexes +FollowSymLinks
|
||||
AllowOverride None
|
||||
<IfModule mod_authz_core.c>
|
||||
# Apache 2.4
|
||||
Require all granted
|
||||
</IfModule>
|
||||
<IfModule !mod_authz_core.c>
|
||||
# Apache 2.2
|
||||
Order deny,allow
|
||||
Allow from all
|
||||
</IfModule>
|
||||
</Directory>
|
||||
|
||||
Alias /zm /usr/share/zoneminder/www
|
||||
<Directory /usr/share/zoneminder/www>
|
||||
Options -Indexes +FollowSymLinks
|
||||
<IfModule mod_dir.c>
|
||||
DirectoryIndex index.php
|
||||
</IfModule>
|
||||
</Directory>
|
||||
|
||||
# For better visibility, the following directives have been migrated from the
|
||||
# default .htaccess files included with the CakePHP project.
|
||||
# Parameters not set here are inherited from the parent directive above.
|
||||
<Directory "/usr/share/zoneminder/www/api">
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ app/webroot/ [L]
|
||||
RewriteRule (.*) app/webroot/$1 [L]
|
||||
RewriteBase /zm/api
|
||||
</Directory>
|
||||
|
||||
<Directory "/usr/share/zoneminder/www/api/app">
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ webroot/ [L]
|
||||
RewriteRule (.*) webroot/$1 [L]
|
||||
RewriteBase /zm/api
|
||||
</Directory>
|
||||
|
||||
<Directory "/usr/share/zoneminder/www/api/app/webroot">
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
RewriteBase /zm/api
|
||||
</Directory>
|
|
@ -0,0 +1,166 @@
|
|||
Source: zoneminder
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Isaac Connor <isaac@zoneminder.com>
|
||||
Uploaders: Isaac Connor <isaac@zoneminder.com>
|
||||
Build-Depends: debhelper, sphinx-doc, dh-linktree, dh-apache2
|
||||
,cmake
|
||||
,libx264-dev, libmp4v2-dev
|
||||
,libavdevice-dev
|
||||
,libavcodec-dev
|
||||
,libavformat-dev
|
||||
,libavutil-dev
|
||||
,libswresample-dev
|
||||
,libswscale-dev
|
||||
,ffmpeg
|
||||
,net-tools
|
||||
,libbz2-dev
|
||||
,libgcrypt20-dev
|
||||
,libcurl4-gnutls-dev
|
||||
,libturbojpeg0-dev
|
||||
,default-libmysqlclient-dev | libmysqlclient-dev | libmariadbclient-dev-compat
|
||||
,libpcre3-dev
|
||||
,libpolkit-gobject-1-dev
|
||||
,libv4l-dev [!hurd-any]
|
||||
,libvlc-dev
|
||||
,libdate-manip-perl
|
||||
,libdbd-mysql-perl
|
||||
,libphp-serialization-perl
|
||||
,libsys-mmap-perl [!hurd-any]
|
||||
,libwww-perl
|
||||
,libdata-uuid-perl
|
||||
,libssl-dev
|
||||
,libcrypt-eksblowfish-perl
|
||||
,libdata-entropy-perl
|
||||
# Unbundled (dh_linktree):
|
||||
,libjs-jquery
|
||||
,libjs-mootools
|
||||
Standards-Version: 3.9.8
|
||||
Homepage: http://www.zoneminder.com/
|
||||
Vcs-Browser: http://anonscm.debian.org/cgit/collab-maint/zoneminder.git
|
||||
Vcs-Git: git://anonscm.debian.org/collab-maint/zoneminder.git
|
||||
|
||||
Package: zoneminder
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
||||
,javascript-common
|
||||
,libmp4v2-2, libx264-155
|
||||
,libswscale5
|
||||
,libswresample3
|
||||
,ffmpeg
|
||||
,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl
|
||||
,libdbd-mysql-perl
|
||||
,libphp-serialization-perl
|
||||
,libmodule-load-conditional-perl
|
||||
,libnet-sftp-foreign-perl
|
||||
,libarchive-zip-perl
|
||||
,libdbd-mysql-perl
|
||||
,libdevice-serialport-perl
|
||||
,libimage-info-perl
|
||||
,libjson-maybexs-perl
|
||||
,libsys-mmap-perl [!hurd-any]
|
||||
,liburi-encode-perl
|
||||
,libwww-perl, liburi-perl
|
||||
,libdata-dump-perl
|
||||
,libdatetime-perl
|
||||
,libclass-std-fast-perl
|
||||
,libsoap-wsdl-perl
|
||||
,libio-socket-multicast-perl
|
||||
,libdigest-sha-perl
|
||||
,libsys-cpu-perl, libsys-meminfo-perl
|
||||
,libdata-uuid-perl
|
||||
,libnumber-bytes-human-perl
|
||||
,libfile-slurp-perl
|
||||
,mysql-client | mariadb-client | virtual-mysql-client
|
||||
,perl-modules
|
||||
,php-mysql, php-gd, php-apcu, php-apc | php-apcu-bc, php-json
|
||||
,policykit-1
|
||||
,rsyslog | system-log-daemon
|
||||
,zip
|
||||
,libpcre3
|
||||
,libcrypt-eksblowfish-perl
|
||||
,libdata-entropy-perl
|
||||
Recommends: ${misc:Recommends}
|
||||
,libapache2-mod-php | php-fpm
|
||||
,mysql-server | mariadb-server | virtual-mysql-server
|
||||
,zoneminder-doc (>= ${source:Version})
|
||||
,ffmpeg
|
||||
Suggests: fcgiwrap, logrotate
|
||||
Description: video camera security and surveillance solution
|
||||
ZoneMinder is intended for use in single or multi-camera video security
|
||||
applications, including commercial or home CCTV, theft prevention and child
|
||||
or family member or home monitoring and other care scenarios. It
|
||||
supports capture, analysis, recording, and monitoring of video data coming
|
||||
from one or more video or network cameras attached to a Linux system.
|
||||
ZoneMinder also support web and semi-automatic control of Pan/Tilt/Zoom
|
||||
cameras using a variety of protocols. It is suitable for use as a home
|
||||
video security system and for commercial or professional video security
|
||||
and surveillance. It can also be integrated into a home automation system
|
||||
via X.10 or other protocols.
|
||||
|
||||
#Package: libzoneminder-perl
|
||||
#Section: perl
|
||||
#Architecture: all
|
||||
#Multi-Arch: foreign
|
||||
#Depends: ${misc:Depends}, ${perl:Depends}
|
||||
# ,libarchive-zip-perl
|
||||
# ,libdbd-mysql-perl
|
||||
# ,libdevice-serialport-perl
|
||||
# ,libimage-info-perl
|
||||
# ,libjson-maybexs-perl
|
||||
# ,libsys-mmap-perl [!hurd-any]
|
||||
# ,liburi-encode-perl
|
||||
# ,libwww-perl
|
||||
#Description: ZoneMinder Perl libraries
|
||||
# ZoneMinder is intended for use in single or multi-camera video security
|
||||
# applications, including commercial or home CCTV, theft prevention and child
|
||||
# or family member or home monitoring and other care scenarios. It
|
||||
# supports capture, analysis, recording, and monitoring of video data coming
|
||||
# from one or more video or network cameras attached to a Linux system.
|
||||
# ZoneMinder also support web and semi-automatic control of Pan/Tilt/Zoom
|
||||
# cameras using a variety of protocols. It is suitable for use as a home
|
||||
# video security system and for commercial or professional video security
|
||||
# and surveillance. It can also be integrated into a home automation system
|
||||
# via X.10 or other protocols.
|
||||
# .
|
||||
# This package provides ZoneMinder Perl libraries; it can be used to
|
||||
# write custom interfaces as well.
|
||||
|
||||
Package: zoneminder-doc
|
||||
Section: doc
|
||||
Architecture: all
|
||||
Multi-Arch: foreign
|
||||
Depends: ${misc:Depends}, ${sphinxdoc:Depends}, python-sphinx-rtd-theme | python3-sphinx-rtd-theme
|
||||
Suggests: www-browser
|
||||
Description: ZoneMinder documentation
|
||||
ZoneMinder is intended for use in single or multi-camera video security
|
||||
applications, including commercial or home CCTV, theft prevention and child
|
||||
or family member or home monitoring and other care scenarios. It
|
||||
supports capture, analysis, recording, and monitoring of video data coming
|
||||
from one or more video or network cameras attached to a Linux system.
|
||||
ZoneMinder also support web and semi-automatic control of Pan/Tilt/Zoom
|
||||
cameras using a variety of protocols. It is suitable for use as a home
|
||||
video security system and for commercial or professional video security
|
||||
and surveillance. It can also be integrated into a home automation system
|
||||
via X.10 or other protocols.
|
||||
.
|
||||
This package provides ZoneMinder documentation in HTML format.
|
||||
|
||||
Package: zoneminder-dbg
|
||||
Section: debug
|
||||
Priority: extra
|
||||
Architecture: any
|
||||
Depends: zoneminder (= ${binary:Version}), ${misc:Depends}
|
||||
Description: Zoneminder -- debugging symbols
|
||||
ZoneMinder is intended for use in single or multi-camera video security
|
||||
applications, including commercial or home CCTV, theft prevention and child
|
||||
or family member or home monitoring and other care scenarios. It
|
||||
supports capture, analysis, recording, and monitoring of video data coming
|
||||
from one or more video or network cameras attached to a Linux system.
|
||||
ZoneMinder also support web and semi-automatic control of Pan/Tilt/Zoom
|
||||
cameras using a variety of protocols. It is suitable for use as a home
|
||||
video security system and for commercial or professional video security
|
||||
and surveillance. It can also be integrated into a home automation system
|
||||
via X.10 or other protocols.
|
||||
.
|
||||
This package provides debugging symbols
|
|
@ -0,0 +1,174 @@
|
|||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: ZoneMinder
|
||||
Upstream-Contact: Philip Coombes <philip.coombes@zoneminder.com>
|
||||
Source: https://github.com/ZoneMinder/ZoneMinder
|
||||
Comment:
|
||||
This package was originally debianized by matrix <matrix@cecilia>
|
||||
on Mon, 7 Mar 2005 02:07:57 -0500.
|
||||
It was re-done for submission to the Debian project by Peter Howard
|
||||
<pjh@northern-ridge.com.au> on Fri, 8 Dec 2006 10:19:43 +1100
|
||||
Files-Excluded:
|
||||
web/skins/*/js/jquery-*
|
||||
web/tools/mootools/*-yc.js
|
||||
|
||||
Files: *
|
||||
Copyright: 2001-2014 Philip Coombes <philip.coombes@zoneminder.com>
|
||||
2008 Brian Rudy <brudyNO@SPAMpraecogito.com>
|
||||
2014 Vincent Giovannone
|
||||
2013 Tim Craig <timcraigNO@SPAMsonic.net>
|
||||
2003-2008 Corey DeLasaux
|
||||
2001-2010 Chris Kistner
|
||||
License: GPL-2+
|
||||
|
||||
Files: distros/*
|
||||
Copyright: 2001-2008 Philip Coombes <philip.coombes@zoneminder.com>
|
||||
2014 Isaac Connor <iconnor@connortechnology.com>
|
||||
2005 Serg Oskin
|
||||
License: GPL-2+
|
||||
|
||||
Files: web/skins/*/js/jquery-*
|
||||
Copyright: 2010 John Resig
|
||||
2010 The Dojo Foundation
|
||||
License: GPL-2 or Expat
|
||||
Comment:
|
||||
Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
http://jquery.org/license
|
||||
.
|
||||
Includes Sizzle.js http://sizzlejs.com/
|
||||
Released under the MIT, BSD, and GPL Licenses.
|
||||
|
||||
Files: web/tools/mootools/*.js
|
||||
Copyright: 2009 Marcelo Jorge Vieira (metal) <metal@alucinados.com>
|
||||
2006-2010 Valerio Proietti (http://mad4milk.net/)
|
||||
License: Expat
|
||||
|
||||
Files: web/api/*
|
||||
Copyright: 2005-2013 Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
License: Expat
|
||||
|
||||
Files:
|
||||
cmake/Modules/CheckPrototypeDefinition*.cmake
|
||||
cmake/Modules/FindGLIB2.cmake
|
||||
cmake/Modules/FindPolkit.cmake
|
||||
cmake/Modules/GNUInstallDirs.cmake
|
||||
Copyright:
|
||||
2005-2011 Kitware, Inc.
|
||||
2010-2011 Andreas Schneider <asn@cryptomilk.org>
|
||||
2009 Dario Freddi <drf@kde.org>
|
||||
2008 Laurent Montel, <montel@kde.org>
|
||||
2011 Nikita Krupen'ko <krnekit@gmail.com>
|
||||
License: BSD-3-clause
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
.
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
.
|
||||
* The names of Kitware, Inc., the Insight Consortium, or the names of
|
||||
any consortium members, or of any contributors, may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Files: cmake/Modules/FindPerlModules.cmake
|
||||
Copyright: 2012 Iowa State University
|
||||
License: Boost-1.0
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
.
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
.
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2015 Dmitry Smirnov <onlyjob@debian.org>
|
||||
2007-2014 Peter Howard <pjh@northern-ridge.com.au>
|
||||
2010-2012 Vagrant Cascadian <vagrant@debian.org>
|
||||
2001-2008 Philip Coombes <philip.coombes@zoneminder.com>
|
||||
License: GPL-2+
|
||||
|
||||
License: Expat
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
License: GPL-2+
|
||||
This package 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 package 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 package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
.
|
||||
The complete text of the GNU General Public License version 2
|
||||
can be found in "/usr/share/common-licenses/GPL-2".
|
||||
|
||||
License: GPL-2
|
||||
This package 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; version 2 of the License.
|
||||
.
|
||||
This package 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 package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
.
|
||||
The complete text of the GNU General Public License version 2
|
||||
can be found in "/usr/share/common-licenses/GPL-2".
|
|
@ -0,0 +1,32 @@
|
|||
location /zm/cgi-bin {
|
||||
gzip off;
|
||||
alias /usr/lib/zoneminder/cgi-bin;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
fastcgi_pass unix:/var/run/fcgiwrap.socket;
|
||||
}
|
||||
|
||||
location /zm {
|
||||
# if ($scheme ~ ^http:){
|
||||
# rewrite ^(.*)$ https://$host$1 permanent;
|
||||
# }
|
||||
|
||||
gzip off;
|
||||
alias /usr/share/zoneminder/www;
|
||||
index index.php;
|
||||
|
||||
location ~ \.php$ {
|
||||
if (!-f $request_filename) { return 404; }
|
||||
expires epoch;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_pass unix:/var/run/php5-fpm.sock;
|
||||
}
|
||||
|
||||
location ~ \.(jpg|jpeg|gif|png|ico)$ {
|
||||
access_log off;
|
||||
expires 33d;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
[dch]
|
||||
id-length = 0
|
||||
|
||||
[import-orig]
|
||||
pristine-tar = False
|
||||
merge = False
|
|
@ -0,0 +1,2 @@
|
|||
usr/share/man/man3
|
||||
usr/share/perl5
|
|
@ -0,0 +1,87 @@
|
|||
#!/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 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_CONFIG_SUBDIR="/etc/zm/conf.d" \
|
||||
-DZM_RUNDIR="/run/zm" \
|
||||
-DZM_SOCKDIR="/run/zm" \
|
||||
-DZM_TMPDIR="/tmp/zm" \
|
||||
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
|
||||
-DZM_CACHEDIR="/var/cache/zoneminder/cache" \
|
||||
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
|
||||
-DZM_PATH_SHUTDOWN="/sbin/shutdown" \
|
||||
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
|
||||
|
||||
override_dh_clean:
|
||||
dh_clean $(MANPAGES1)
|
||||
$(RM) -r docs/_build
|
||||
|
||||
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_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
|
|
@ -0,0 +1 @@
|
|||
3.0 (quilt)
|
|
@ -0,0 +1,9 @@
|
|||
## Actually sources are there: "*-nc.js".
|
||||
source-is-missing web/tools/mootools/mootools-*-yc.js
|
||||
|
||||
## We're using "libjs-jquery" instead.
|
||||
source-is-missing web/skins/*/js/jquery-1.4.2.min.js
|
||||
|
||||
## Acknowledged, will repack eventually.
|
||||
source-contains-prebuilt-javascript-object web/tools/mootools/mootools-*-yc.js
|
||||
source-contains-prebuilt-javascript-object web/skins/*/js/jquery-1.4.2.min.js
|
|
@ -0,0 +1,8 @@
|
|||
Document: zoneminder-doc
|
||||
Title: Zoneminder documentation
|
||||
Abstract: This document describes how to use Zoneminder.
|
||||
Section: System/Administration
|
||||
|
||||
Format: HTML
|
||||
Index: /usr/share/doc/zoneminder-doc/html/index.html
|
||||
Files: /usr/share/doc/zoneminder-doc/html/*
|
|
@ -0,0 +1 @@
|
|||
docs/_build/html usr/share/doc/zoneminder-doc/
|
|
@ -0,0 +1,2 @@
|
|||
## Convenience symlink:
|
||||
/usr/share/doc/zoneminder-doc/html /usr/share/doc/zoneminder/html
|
|
@ -0,0 +1 @@
|
|||
conf debian/conf/apache2/zoneminder.conf nginx
|
|
@ -0,0 +1,5 @@
|
|||
Unless bug is specific to Debian please consider reporting it directly to
|
||||
upstream developer(s):
|
||||
|
||||
https://github.com/ZoneMinder/ZoneMinder/issues
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
var/log/zm
|
||||
var/lib/zm
|
||||
var/cache/zoneminder/events
|
||||
var/cache/zoneminder/images
|
||||
var/cache/zoneminder/temp
|
||||
var/cache/zoneminder/cache
|
||||
usr/share/zoneminder/db
|
||||
etc/zm/
|
||||
etc/zm/conf.d
|
|
@ -0,0 +1 @@
|
|||
README.md
|
|
@ -0,0 +1,2 @@
|
|||
debian/examples/*
|
||||
dbuild/misc/apache.conf
|
|
@ -0,0 +1,91 @@
|
|||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: zoneminder
|
||||
# Required-Start: $network $remote_fs $syslog
|
||||
# Required-Stop: $network $remote_fs $syslog
|
||||
# Should-Start: mysql
|
||||
# Should-Stop: mysql
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Control ZoneMinder as a Service
|
||||
# Description: ZoneMinder CCTV recording and surveillance system
|
||||
### END INIT INFO
|
||||
# chkconfig: 2345 20 20
|
||||
|
||||
# Source function library.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
prog=ZoneMinder
|
||||
ZM_PATH_BIN="/usr/bin"
|
||||
RUNDIR="/run/zm"
|
||||
TMPDIR="/tmp/zm"
|
||||
command="$ZM_PATH_BIN/zmpkg.pl"
|
||||
|
||||
start() {
|
||||
echo -n "Starting $prog: "
|
||||
export TZ=:/etc/localtime
|
||||
mkdir -p "$RUNDIR" && chown www-data:www-data "$RUNDIR"
|
||||
mkdir -p "$TMPDIR" && chown www-data:www-data "$TMPDIR"
|
||||
$command start
|
||||
RETVAL=$?
|
||||
[ $RETVAL = 0 ] && echo success
|
||||
[ $RETVAL != 0 ] && echo failure
|
||||
echo
|
||||
[ $RETVAL = 0 ] && touch /var/lock/zm
|
||||
return $RETVAL
|
||||
}
|
||||
stop() {
|
||||
echo -n "Stopping $prog: "
|
||||
#
|
||||
# Why is this status check being done?
|
||||
# as $command stop returns 1 if zoneminder
|
||||
# is stopped, which will result in
|
||||
# this returning 1, which will stuff
|
||||
# dpkg when it tries to stop zoneminder before
|
||||
# uninstalling . . .
|
||||
#
|
||||
result=`$command status`
|
||||
if [ ! "$result" = "running" ]; then
|
||||
echo "Zoneminder already stopped"
|
||||
echo
|
||||
RETVAL=0
|
||||
else
|
||||
$command stop
|
||||
RETVAL=$?
|
||||
[ $RETVAL = 0 ] && echo success
|
||||
[ $RETVAL != 0 ] && echo failure
|
||||
echo
|
||||
[ $RETVAL = 0 ] && rm -f /var/lock/zm
|
||||
fi
|
||||
}
|
||||
status() {
|
||||
result=`$command status`
|
||||
if [ "$result" = "running" ]; then
|
||||
echo "ZoneMinder is running"
|
||||
RETVAL=0
|
||||
else
|
||||
echo "ZoneMinder is stopped"
|
||||
RETVAL=1
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
'start')
|
||||
start
|
||||
;;
|
||||
'stop')
|
||||
stop
|
||||
;;
|
||||
'restart' | 'force-reload')
|
||||
stop
|
||||
start
|
||||
;;
|
||||
'status')
|
||||
status
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 { start | stop | restart | status }"
|
||||
RETVAL=1
|
||||
;;
|
||||
esac
|
||||
exit $RETVAL
|
|
@ -0,0 +1,11 @@
|
|||
etc/zm/zm.conf
|
||||
etc/zm/conf.d/*
|
||||
usr/bin
|
||||
usr/lib/zoneminder
|
||||
usr/share/polkit-1
|
||||
usr/share/zoneminder/db
|
||||
usr/share/zoneminder/www
|
||||
|
||||
# libzoneminder-perl files:
|
||||
usr/share/man/man3
|
||||
usr/share/perl5
|
|
@ -0,0 +1 @@
|
|||
/var/tmp /usr/share/zoneminder/www/api/app/tmp
|
|
@ -0,0 +1,14 @@
|
|||
## cakephp
|
||||
#replace /usr/share/php/Cake /usr/share/zoneminder/www/api/lib/Cake
|
||||
|
||||
## libjs-mootools
|
||||
replace /usr/share/javascript/mootools/mootools.js /usr/share/zoneminder/www/tools/mootools/mootools-core.js
|
||||
replace /usr/share/javascript/mootools/mootools.js /usr/share/zoneminder/www/tools/mootools/mootools-core-1.3.2-nc.js
|
||||
replace /usr/share/javascript/mootools/mootools.js /usr/share/zoneminder/www/tools/mootools/mootools-core-1.3.2-yc.js
|
||||
replace /usr/share/javascript/mootools/mootools-more.js /usr/share/zoneminder/www/tools/mootools/mootools-more.js
|
||||
replace /usr/share/javascript/mootools/mootools-more.js /usr/share/zoneminder/www/tools/mootools/mootools-more-1.3.2.1-nc.js
|
||||
replace /usr/share/javascript/mootools/mootools-more.js /usr/share/zoneminder/www/tools/mootools/mootools-more-1.3.2.1-yc.js
|
||||
|
||||
## libjs-jquery
|
||||
replace /usr/share/javascript/jquery/jquery.min.js /usr/share/zoneminder/www/skins/classic/js/jquery-1.4.2.min.js
|
||||
replace /usr/share/javascript/jquery/jquery.min.js /usr/share/zoneminder/www/skins/flat/js/jquery-1.4.2.min.js
|
|
@ -0,0 +1,14 @@
|
|||
# Depends: policykit-1
|
||||
unusual-interpreter usr/bin/zmsystemctl.pl #!/usr/bin/pkexec
|
||||
|
||||
# Intentionally not others-readable, #637685.
|
||||
non-standard-file-perm etc/zm/zm.conf 0640 != 0644
|
||||
|
||||
# Bundled Cake PHP framework, not intended for direct execution:
|
||||
script-not-executable usr/share/zoneminder/www/api/*
|
||||
|
||||
# Annoying but seems to be too much troubles to fix; should be fixed upstream:
|
||||
script-with-language-extension usr/bin/*.pl
|
||||
|
||||
# dh-linktree:
|
||||
package-contains-broken-symlink usr/share/zoneminder/www/api/lib/Cake/*
|
|
@ -0,0 +1,13 @@
|
|||
/var/log/zm/*.log {
|
||||
missingok
|
||||
notifempty
|
||||
sharedscripts
|
||||
delaycompress
|
||||
compress
|
||||
postrotate
|
||||
/usr/bin/zmpkg.pl logrot >>/dev/null 2>&1 || :
|
||||
endscript
|
||||
daily
|
||||
rotate 7
|
||||
maxage 7
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
rm_conffile /etc/zm/apache.conf 1.28.1-5~
|
|
@ -0,0 +1 @@
|
|||
docs/_build/man/*.1
|
|
@ -0,0 +1,66 @@
|
|||
#! /bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$1" = "configure" ]; then
|
||||
|
||||
. /etc/zm/zm.conf
|
||||
for i in /etc/zm/conf.d/*.conf; do
|
||||
. $i
|
||||
done;
|
||||
|
||||
|
||||
# The logs can contain passwords, etc... so by setting group root, only www-data can read them, not people in the www-data group
|
||||
chown www-data:root /var/log/zm
|
||||
chown www-data:www-data /var/lib/zm
|
||||
if [ -z "$2" ]; then
|
||||
chown www-data:www-data /var/cache/zoneminder /var/cache/zoneminder/*
|
||||
fi
|
||||
|
||||
# Do this every time the package is installed or upgraded
|
||||
# Ensure zoneminder is stopped
|
||||
invoke-rc.d zoneminder stop || true
|
||||
|
||||
if [ "$ZM_DB_HOST" = "localhost" ]; then
|
||||
if [ -e "/etc/init.d/mysql" ]; then
|
||||
#
|
||||
# Get mysql started if it isn't
|
||||
#
|
||||
if ! $(/etc/init.d/mysql status >/dev/null 2>&1); then
|
||||
invoke-rc.d mysql start
|
||||
fi
|
||||
if $(/etc/init.d/mysql status >/dev/null 2>&1); then
|
||||
mysqladmin --defaults-file=/etc/mysql/debian.cnf -f reload
|
||||
# test if database if already present...
|
||||
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
|
||||
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error creating db."
|
||||
exit 1;
|
||||
fi
|
||||
# This creates the user.
|
||||
echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
else
|
||||
echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
fi
|
||||
|
||||
zmupdate.pl --nointeractive
|
||||
zmupdate.pl --nointeractive -f
|
||||
|
||||
# Add any new PTZ control configurations to the database (will not overwrite)
|
||||
zmcamtool.pl --import >/dev/null 2>&1
|
||||
|
||||
else
|
||||
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
|
||||
fi
|
||||
else
|
||||
echo 'mysql not found, assuming remote server.'
|
||||
fi
|
||||
else
|
||||
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
|
||||
fi
|
||||
echo "Done Updating, starting ZoneMinder"
|
||||
invoke-rc.d zoneminder start || true
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
|
@ -0,0 +1,14 @@
|
|||
#! /bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$1" = "purge" ]; then
|
||||
echo "
|
||||
Reminder: to completely remove \"zoneminder\" it may be necessary
|
||||
* to delete database using the following sample command:
|
||||
sudo mysqladmin --defaults-file=/etc/mysql/debian.cnf -f drop zm
|
||||
* to delete remaining data files in "/var/cache/zoneminder".
|
||||
"
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
## Remove obsolete symlink which is in the way of dh_apache2:
|
||||
ol="/etc/apache2/conf-available/zoneminder.conf"
|
||||
if [ -h "${ol}" ]; then
|
||||
[ "$(readlink ${ol})" = "/etc/zm/apache.conf" ] && rm -f "${ol}"
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
|
@ -0,0 +1,4 @@
|
|||
d /run/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/cache/zoneminder/cache 0755 www-data www-data
|
|
@ -28,7 +28,7 @@
|
|||
%global _hardened_build 1
|
||||
|
||||
Name: zoneminder
|
||||
Version: 1.34.14
|
||||
Version: 1.34.20
|
||||
Release: 1%{?dist}
|
||||
Summary: A camera monitoring and analysis tool
|
||||
Group: System Environment/Daemons
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
zoneminder (1.31.39~20180223.27-stretch-1) unstable; urgency=low
|
||||
zoneminder (1.35.6~20200825.27-xenial) xenial; urgency=low
|
||||
*
|
||||
-- Isaac Connor <iconnor@connortechnology.com> Fri, 23 Feb 2018 14:15:59 -0500
|
||||
-- Isaac Connor <isaac@zoneminder.com> Tue, 25 Aug 2020 09:28:18 -0400
|
||||
|
|
|
@ -29,7 +29,7 @@ configure_file(zm.in "${CMAKE_CURRENT_BINARY_DIR}/zm" @ONLY)
|
|||
#configure_file(zmeventdump.in zmeventdump @ONLY)
|
||||
|
||||
# Generate man files for the perl scripts destined for the bin folder
|
||||
file(GLOB perlscripts "*.pl")
|
||||
file(GLOB perlscripts "${CMAKE_CURRENT_BINARY_DIR}/*.pl")
|
||||
FOREACH(PERLSCRIPT ${perlscripts})
|
||||
get_filename_component(PERLSCRIPTNAME ${PERLSCRIPT} NAME)
|
||||
POD2MAN(${PERLSCRIPT} zoneminder-${PERLSCRIPTNAME} 8 ${ZM_MANPAGE_DEST_PREFIX})
|
||||
|
|
|
@ -69,7 +69,7 @@ sub sendCmd {
|
|||
|
||||
my $result = undef;
|
||||
|
||||
printMsg($cmd, 'Tx');
|
||||
$self->printMsg($cmd, 'Tx');
|
||||
|
||||
my $req = HTTP::Request->new(POST=>"http://$self->{Monitor}->{ControlAddress}/$cgi.cgi");
|
||||
$req->content($cmd);
|
||||
|
|
|
@ -143,10 +143,10 @@ sub PutCmd {
|
|||
} else {
|
||||
Info('Missing username and password in Control Address.');
|
||||
}
|
||||
Fatal($res->status_line);
|
||||
Error($res->status_line);
|
||||
}
|
||||
} else {
|
||||
Fatal($res->status_line);
|
||||
Error($res->status_line);
|
||||
}
|
||||
} # end unless res->is_success
|
||||
} # end sub putCmd
|
||||
|
|
|
@ -49,9 +49,9 @@ my %options;
|
|||
GetOptions(
|
||||
'id=i' =>\$id,
|
||||
'command=s' =>\$options{command},
|
||||
'xcoord=i' =>\$options{xcoord},
|
||||
'ycoord=i' =>\$options{ycoord},
|
||||
'speed=i' =>\$options{speed},
|
||||
'xcoord=f' =>\$options{xcoord},
|
||||
'ycoord=f' =>\$options{ycoord},
|
||||
'speed=f' =>\$options{speed},
|
||||
'step=i' =>\$options{step},
|
||||
'panspeed=i' =>\$options{panspeed},
|
||||
'tiltspeed=i' =>\$options{tiltspeed},
|
||||
|
|
|
@ -160,7 +160,7 @@ if ( !$server_up ) {
|
|||
use ZoneMinder::Server qw(CpuLoad);
|
||||
if ( ! defined $dbh->do(q{UPDATE Servers SET Status=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?}, undef,
|
||||
'NotRunning', &totalmem, &freemem, &totalswap, &freeswap, $Config{ZM_SERVER_ID} ) ) {
|
||||
Error("Failed Updating status of Server record to Not RUnning for Id=$Config{ZM_SERVER_ID}" . $dbh->errstr());
|
||||
Error('Failed Updating status of Server record to Not Running for Id='.$Config{ZM_SERVER_ID}.': '.$dbh->errstr());
|
||||
}
|
||||
}
|
||||
# Server is not up. Some commands can still be handled
|
||||
|
@ -191,8 +191,8 @@ if ( !$server_up ) {
|
|||
my $attempts = 0;
|
||||
while ( !connect(CLIENT, $saddr) ) {
|
||||
$attempts++;
|
||||
Debug('Waiting for zmdc.pl server process at '.SOCK_FILE.", attempt $attempts");
|
||||
Fatal("Can't connect: $!") if $attempts > MAX_CONNECT_DELAY;
|
||||
Debug('Waiting for zmdc.pl server process at '.SOCK_FILE.', attempt '.$attempts);
|
||||
Fatal('Can\'t connect to zmdc.pl server process at '.SOCK_FILE.': '.$!) if $attempts > MAX_CONNECT_DELAY;
|
||||
usleep(200000);
|
||||
} # end while
|
||||
} elsif ( defined($cpid) ) {
|
||||
|
@ -255,7 +255,7 @@ sub run {
|
|||
close($PID);
|
||||
} else {
|
||||
# Log not initialized at this point so use die instead
|
||||
die "Can't open pid file at ".ZM_PID."\n";
|
||||
die 'Can\'t open pid file at '.ZM_PID."\n";
|
||||
}
|
||||
|
||||
my $fd = 0;
|
||||
|
@ -308,6 +308,7 @@ sub run {
|
|||
while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) {
|
||||
Warning("Not connected to db ($dbh)".($dbh?' ping('.$dbh->ping().')':''). ($DBI::errstr?" errstr($DBI::errstr)":'').' Reconnecting');
|
||||
$dbh = zmDbConnect();
|
||||
sleep 10 if !$dbh;
|
||||
}
|
||||
last if $zm_terminate;
|
||||
|
||||
|
|
|
@ -48,6 +48,49 @@ while( 1 ) {
|
|||
$dbh->do('DELETE FROM Events_Week WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 week)') or Error($dbh->errstr());
|
||||
$dbh->do('DELETE FROM Events_Month WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 month)') or Error($dbh->errstr());
|
||||
|
||||
# Prune the Logs table if required
|
||||
if ( $Config{ZM_LOG_DATABASE_LIMIT} ) {
|
||||
if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^\d+$/ ) {
|
||||
# Number of rows
|
||||
my $selectLogRowCountSql = 'SELECT count(*) AS `Rows` FROM `Logs`';
|
||||
my $selectLogRowCountSth = $dbh->prepare_cached( $selectLogRowCountSql )
|
||||
or Fatal("Can't prepare '$selectLogRowCountSql': ".$dbh->errstr());
|
||||
my $res = $selectLogRowCountSth->execute()
|
||||
or Fatal("Can't execute: ".$selectLogRowCountSth->errstr());
|
||||
my $row = $selectLogRowCountSth->fetchrow_hashref();
|
||||
my $logRows = $row->{Rows};
|
||||
if ( $logRows > $Config{ZM_LOG_DATABASE_LIMIT} ) {
|
||||
my $deleteLogByRowsSql = 'DELETE low_priority FROM `Logs` ORDER BY `TimeKey` ASC LIMIT ?';
|
||||
my $deleteLogByRowsSth = $dbh->prepare_cached( $deleteLogByRowsSql )
|
||||
or Fatal("Can't prepare '$deleteLogByRowsSql': ".$dbh->errstr());
|
||||
$res = $deleteLogByRowsSth->execute( $logRows - $Config{ZM_LOG_DATABASE_LIMIT} )
|
||||
or Fatal("Can't execute: ".$deleteLogByRowsSth->errstr());
|
||||
if ( $deleteLogByRowsSth->rows() ) {
|
||||
Debug('Deleted '.$deleteLogByRowsSth->rows().' log table entries by count');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Time of record
|
||||
|
||||
# 7 days is invalid. We need to remove the s
|
||||
if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^(.*)s$/ ) {
|
||||
$Config{ZM_LOG_DATABASE_LIMIT} = $1;
|
||||
}
|
||||
my $deleted_rows;
|
||||
do {
|
||||
my $deleteLogByTimeSql =
|
||||
'DELETE FROM `Logs`
|
||||
WHERE `TimeKey` < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.') LIMIT 100';
|
||||
my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql )
|
||||
or Fatal("Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr());
|
||||
my $res = $deleteLogByTimeSth->execute()
|
||||
or Fatal("Can't execute: ".$deleteLogByTimeSth->errstr());
|
||||
$deleted_rows = $deleteLogByTimeSth->rows();
|
||||
Debug("Deleted $deleted_rows log table entries by time");
|
||||
} while ( $deleted_rows );
|
||||
}
|
||||
} # end if ZM_LOG_DATABASE_LIMIT
|
||||
|
||||
sleep($Config{ZM_STATS_UPDATE_INTERVAL});
|
||||
} # end while (1)
|
||||
|
||||
|
|
|
@ -119,7 +119,6 @@ if ( !$monitor->{CanMoveMap} ) {
|
|||
}
|
||||
}
|
||||
|
||||
Debug("Found monitor for id '$monitor'");
|
||||
exit(-1) if !zmMemVerify($monitor);
|
||||
|
||||
sub Suspend {
|
||||
|
|
|
@ -121,6 +121,8 @@ GetOptions(
|
|||
my $dbh = zmDbConnect(undef, { mysql_multi_statements=>1 } );
|
||||
$Config{ZM_DB_USER} = $dbUser;
|
||||
$Config{ZM_DB_PASS} = $dbPass;
|
||||
# we escape dbpass with single quotes so that $ in the password has no effect, but dbpass could have a ' in it.
|
||||
$dbPass =~ s/'/\\'/g;
|
||||
|
||||
if ( ! ($check || $freshen || $rename || $zoneFix || $migrateEvents || $version) ) {
|
||||
if ( $Config{ZM_DYN_DB_VERSION} ) {
|
||||
|
@ -384,21 +386,22 @@ if ( $version ) {
|
|||
my $command = 'mysqldump';
|
||||
if ( defined($portOrSocket) ) {
|
||||
if ( $portOrSocket =~ /^\// ) {
|
||||
$command .= " -S".$portOrSocket;
|
||||
$command .= ' -S'.$portOrSocket;
|
||||
} else {
|
||||
$command .= " -h".$host." -P".$portOrSocket;
|
||||
$command .= ' -h'.$host.' -P'.$portOrSocket;
|
||||
}
|
||||
} else {
|
||||
$command .= " -h".$host;
|
||||
$command .= ' -h'.$host;
|
||||
}
|
||||
if ( $dbUser ) {
|
||||
$command .= ' -u'.$dbUser;
|
||||
$command .= ' -p"'.$dbPass.'"' if $dbPass;
|
||||
$command .= ' -p\''.$dbPass.'\'' if $dbPass;
|
||||
}
|
||||
my $backup = "@ZM_TMPDIR@/".$Config{ZM_DB_NAME}."-".$version.".dump";
|
||||
$command .= " --add-drop-table --databases ".$Config{ZM_DB_NAME}." > ".$backup;
|
||||
my $backup = '@ZM_TMPDIR@/'.$Config{ZM_DB_NAME}.'-'.$version.'.dump';
|
||||
$command .= ' --add-drop-table --databases '.$Config{ZM_DB_NAME}.' > '.$backup;
|
||||
print("Creating backup to $backup. This may take several minutes.\n");
|
||||
print( "Executing '$command'\n" ) if ( logDebugging() );
|
||||
($command) = $command =~ /(.*)/; # detaint
|
||||
print("Executing '$command'\n") if logDebugging();
|
||||
my $output = qx($command);
|
||||
my $status = $? >> 8;
|
||||
if ( $status || logDebugging() ) {
|
||||
|
@ -969,7 +972,7 @@ sub patchDB {
|
|||
my $dbh = shift;
|
||||
my $version = shift;
|
||||
|
||||
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
|
||||
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ) if $Config{ZM_DB_HOST};
|
||||
my $command = 'mysql';
|
||||
if ( defined($portOrSocket) ) {
|
||||
if ( $portOrSocket =~ /^\// ) {
|
||||
|
@ -977,12 +980,12 @@ sub patchDB {
|
|||
} else {
|
||||
$command .= ' -h'.$host.' -P'.$portOrSocket;
|
||||
}
|
||||
} else {
|
||||
} elsif ( $host ) {
|
||||
$command .= ' -h'.$host;
|
||||
}
|
||||
if ( $dbUser ) {
|
||||
$command .= ' -u'.$dbUser;
|
||||
$command .= ' -p"'.$dbPass.'"' if $dbPass;
|
||||
$command .= ' -p\''.$dbPass.'\'' if $dbPass;
|
||||
}
|
||||
$command .= ' '.$Config{ZM_DB_NAME}.' < ';
|
||||
if ( $updateDir ) {
|
||||
|
|
|
@ -48,11 +48,12 @@ Camera::Camera(
|
|||
record_audio(p_record_audio),
|
||||
bytes(0)
|
||||
{
|
||||
linesize = width * colours;
|
||||
pixels = width * height;
|
||||
imagesize = pixels * colours;
|
||||
imagesize = height * linesize;
|
||||
|
||||
Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",
|
||||
monitor_id, width, height, colours, subpixelorder, capture);
|
||||
Debug(2, "New camera id: %d width: %d line size: %d height: %d colours: %d subpixelorder: %d capture: %d",
|
||||
monitor_id, width, linesize, height, colours, subpixelorder, capture);
|
||||
|
||||
monitor = NULL;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ protected:
|
|||
Monitor * monitor; // Null on instantiation, set as soon as possible.
|
||||
SourceType type;
|
||||
unsigned int width;
|
||||
unsigned int linesize;
|
||||
unsigned int height;
|
||||
unsigned int colours;
|
||||
unsigned int subpixelorder;
|
||||
|
@ -69,6 +70,7 @@ public:
|
|||
bool IsLibvlc() const { return type == LIBVLC_SRC; }
|
||||
bool IscURL() const { return type == CURL_SRC; }
|
||||
unsigned int Width() const { return width; }
|
||||
unsigned int LineSize() const { return linesize; }
|
||||
unsigned int Height() const { return height; }
|
||||
unsigned int Colours() const { return colours; }
|
||||
unsigned int SubpixelOrder() const { return subpixelorder; }
|
||||
|
|
|
@ -206,7 +206,12 @@ Event::Event(
|
|||
/* X264 MP4 video writer */
|
||||
if ( monitor->GetOptVideoWriter() == Monitor::X264ENCODE ) {
|
||||
#if ZM_HAVE_VIDEOWRITER_X264MP4
|
||||
videowriter = new X264MP4Writer(video_file, monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder(), monitor->GetOptEncoderParams());
|
||||
videowriter = new X264MP4Writer(video_file,
|
||||
monitor->Width(),
|
||||
monitor->Height(),
|
||||
monitor->Colours(),
|
||||
monitor->SubpixelOrder(),
|
||||
monitor->GetOptEncoderParamsVec());
|
||||
#else
|
||||
Error("ZoneMinder was not compiled with the X264 MP4 video writer, check dependencies (x264 and mp4v2)");
|
||||
#endif
|
||||
|
|
|
@ -807,29 +807,38 @@ Debug(1, "Loading image");
|
|||
|
||||
if ( send_raw ) {
|
||||
#if HAVE_SENDFILE
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", (int)filestat.st_size);
|
||||
if ( 0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", (int)filestat.st_size) ) {
|
||||
fclose(fdj); /* Close the file handle */
|
||||
Info("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if ( zm_sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size) != (int)filestat.st_size ) {
|
||||
/* sendfile() failed, use standard way instead */
|
||||
img_buffer_size = fread(img_buffer, 1, sizeof(temp_img_buffer), fdj);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
fclose(fdj); /* Close the file handle */
|
||||
Error("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
||||
Info("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
if (
|
||||
(0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size) )
|
||||
||
|
||||
( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 )
|
||||
) {
|
||||
fclose(fdj); /* Close the file handle */
|
||||
Error("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
||||
Info("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
fclose(fdj); /* Close the file handle */
|
||||
} else {
|
||||
Debug(3, "Content length: %d", img_buffer_size);
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
if (
|
||||
(0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size) )
|
||||
||
|
||||
( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) ) {
|
||||
Error("Unable to send stream frame: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ extern "C" {
|
|||
#include <libavutil/mathematics.h>
|
||||
#include <libavutil/avstring.h>
|
||||
#include "libavutil/audio_fifo.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
|
||||
/* LIBAVUTIL_VERSION_CHECK checks for the right version of libav and FFmpeg
|
||||
* The original source is vlc (in modules/codec/avcodec/avcommon_compat.h)
|
||||
|
|
|
@ -174,6 +174,20 @@ FfmpegCamera::FfmpegCamera(
|
|||
} else {
|
||||
Panic("Unexpected colours: %d", colours);
|
||||
}
|
||||
|
||||
// sws_scale needs 32bit aligned width and an extra 16 bytes padding, so recalculate imagesize, which was width*height*bytes_per_pixel
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
alignment = 32;
|
||||
imagesize = av_image_get_buffer_size(imagePixFormat, width, height, alignment);
|
||||
// av_image_get_linesize isn't aligned, so we have to do that.
|
||||
linesize = FFALIGN(av_image_get_linesize(imagePixFormat, width, 0), alignment);
|
||||
#else
|
||||
alignment = 1;
|
||||
linesize = FFALIGN(av_image_get_linesize(imagePixFormat, width, 0), alignment);
|
||||
imagesize = avpicture_get_size(imagePixFormat, width, height);
|
||||
#endif
|
||||
|
||||
Debug(1, "ffmpegcamera: width %d height %d linesize %d colours %d imagesize %d", width, height, linesize, colours, imagesize);
|
||||
} // FfmpegCamera::FfmpegCamera
|
||||
|
||||
FfmpegCamera::~FfmpegCamera() {
|
||||
|
@ -194,12 +208,12 @@ void FfmpegCamera::Terminate() {
|
|||
|
||||
int FfmpegCamera::PrimeCapture() {
|
||||
if ( mCanCapture ) {
|
||||
Info("Priming capture from %s, Closing", mPath.c_str());
|
||||
Debug(1, "Priming capture from %s, Closing", mPath.c_str());
|
||||
Close();
|
||||
}
|
||||
mVideoStreamId = -1;
|
||||
mAudioStreamId = -1;
|
||||
Info("Priming capture from %s", mPath.c_str());
|
||||
Debug(1, "Priming capture from %s", mPath.c_str());
|
||||
|
||||
return OpenFfmpeg();
|
||||
}
|
||||
|
@ -608,16 +622,6 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
mFrame->width = width;
|
||||
mFrame->height = height;
|
||||
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
int pSize = av_image_get_buffer_size(imagePixFormat, width, height, 1);
|
||||
#else
|
||||
int pSize = avpicture_get_size(imagePixFormat, width, height);
|
||||
#endif
|
||||
|
||||
if ( (unsigned int)pSize != imagesize ) {
|
||||
Error("Image size mismatch. Required: %d Available: %d", pSize, imagesize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
if ( !sws_isSupportedInput(mVideoCodecContext->pix_fmt) ) {
|
||||
|
@ -976,10 +980,12 @@ int FfmpegCamera::CaptureAndRecord(
|
|||
return -1;
|
||||
}
|
||||
#if HAVE_LIBAVUTIL_HWCONTEXT_H
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 89, 0, 89, 0)
|
||||
if ( (ret == AVERROR_INVALIDDATA ) && (hw_pix_fmt != AV_PIX_FMT_NONE) ) {
|
||||
use_hwaccel = false;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
zm_av_packet_unref(&packet);
|
||||
|
@ -1087,11 +1093,18 @@ int FfmpegCamera::transfer_to_image(
|
|||
int size = av_image_fill_arrays(
|
||||
output_frame->data, output_frame->linesize,
|
||||
directbuffer, imagePixFormat, width, height,
|
||||
(AV_PIX_FMT_RGBA == imagePixFormat ? 32 : 1)
|
||||
alignment
|
||||
);
|
||||
if ( size < 0 ) {
|
||||
Error("Problem setting up data pointers into image %s",
|
||||
av_make_error_string(size).c_str());
|
||||
} else {
|
||||
Debug(4, "av_image_fill_array %dx%d alignment: %d = %d, buffer size is %d",
|
||||
width, height, alignment, size, image.Size());
|
||||
}
|
||||
Debug(1, "ffmpegcamera: width %d height %d linesize %d colours %d imagesize %d", width, height, linesize, colours, imagesize);
|
||||
if ( linesize != (unsigned int)output_frame->linesize[0] ) {
|
||||
Error("Bad linesize expected %d got %d", linesize, output_frame->linesize[0]);
|
||||
}
|
||||
#else
|
||||
avpicture_fill((AVPicture *)output_frame, directbuffer,
|
||||
|
|
|
@ -46,6 +46,8 @@ class FfmpegCamera : public Camera {
|
|||
|
||||
int frameCount;
|
||||
|
||||
int alignment; /* ffmpeg wants line sizes to be 32bit aligned. Especially 4.3+ */
|
||||
|
||||
#if HAVE_LIBAVFORMAT
|
||||
AVFormatContext *mFormatContext;
|
||||
int mVideoStreamId;
|
||||
|
|
|
@ -19,7 +19,7 @@ FFmpeg_Input::~FFmpeg_Input() {
|
|||
avcodec_close(streams[i].context);
|
||||
streams[i].context = NULL;
|
||||
}
|
||||
delete streams;
|
||||
delete[] streams;
|
||||
streams = NULL;
|
||||
}
|
||||
if ( frame ) {
|
||||
|
|
396
src/zm_image.cpp
396
src/zm_image.cpp
|
@ -108,6 +108,7 @@ Image::Image() {
|
|||
if ( !initialised )
|
||||
Initialise();
|
||||
width = 0;
|
||||
linesize = 0;
|
||||
height = 0;
|
||||
pixels = 0;
|
||||
colours = 0;
|
||||
|
@ -125,6 +126,7 @@ Image::Image( const char *filename ) {
|
|||
if ( !initialised )
|
||||
Initialise();
|
||||
width = 0;
|
||||
linesize = 0;
|
||||
height = 0;
|
||||
pixels = 0;
|
||||
colours = 0;
|
||||
|
@ -139,15 +141,42 @@ Image::Image( const char *filename ) {
|
|||
update_function_pointers();
|
||||
}
|
||||
|
||||
Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer ) {
|
||||
Image::Image(int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer, unsigned int p_padding) {
|
||||
if ( !initialised )
|
||||
Initialise();
|
||||
width = p_width;
|
||||
height = p_height;
|
||||
pixels = width*height;
|
||||
colours = p_colours;
|
||||
linesize = p_width * p_colours;
|
||||
padding = p_padding;
|
||||
subpixelorder = p_subpixelorder;
|
||||
size = pixels*colours;
|
||||
size = linesize*height + padding;
|
||||
buffer = 0;
|
||||
holdbuffer = 0;
|
||||
if ( p_buffer ) {
|
||||
allocation = size;
|
||||
buffertype = ZM_BUFTYPE_DONTFREE;
|
||||
buffer = p_buffer;
|
||||
} else {
|
||||
AllocImgBuffer(size);
|
||||
}
|
||||
text[0] = '\0';
|
||||
|
||||
update_function_pointers();
|
||||
}
|
||||
|
||||
Image::Image(int p_width, int p_linesize, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer, unsigned int p_padding) {
|
||||
if ( !initialised )
|
||||
Initialise();
|
||||
width = p_width;
|
||||
linesize = p_linesize;
|
||||
height = p_height;
|
||||
pixels = width*height;
|
||||
colours = p_colours;
|
||||
padding = p_padding;
|
||||
subpixelorder = p_subpixelorder;
|
||||
size = linesize*height + padding;
|
||||
buffer = 0;
|
||||
holdbuffer = 0;
|
||||
if ( p_buffer ) {
|
||||
|
@ -169,18 +198,25 @@ Image::Image(const AVFrame *frame) {
|
|||
width = frame->width;
|
||||
height = frame->height;
|
||||
pixels = width*height;
|
||||
|
||||
colours = ZM_COLOUR_RGB32;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
|
||||
size = pixels*colours;
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
size = av_image_get_buffer_size(AV_PIX_FMT_RGBA, width, height, 32);
|
||||
// av_image_get_linesize isn't aligned, so we have to do that.
|
||||
linesize = FFALIGN(av_image_get_linesize(AV_PIX_FMT_RGBA, width, 0), 32);
|
||||
#else
|
||||
linesize = FFALIGN(av_image_get_linesize(AV_PIX_FMT_RGBA, width, 0), 1);
|
||||
size = avpicture_get_size(AV_PIX_FMT_RGBA, width, height);
|
||||
#endif
|
||||
|
||||
buffer = 0;
|
||||
holdbuffer = 0;
|
||||
AllocImgBuffer(size);
|
||||
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
av_image_fill_arrays(dest_frame->data, dest_frame->linesize,
|
||||
buffer, AV_PIX_FMT_RGBA, width, height, 1);
|
||||
buffer, AV_PIX_FMT_RGBA, width, height, 32);
|
||||
#else
|
||||
avpicture_fill( (AVPicture *)dest_frame, buffer,
|
||||
AV_PIX_FMT_RGBA, width, height);
|
||||
|
@ -212,6 +248,7 @@ Image::Image(const Image &p_image) {
|
|||
if ( !initialised )
|
||||
Initialise();
|
||||
width = p_image.width;
|
||||
linesize = p_image.linesize;
|
||||
height = p_image.height;
|
||||
pixels = p_image.pixels;
|
||||
colours = p_image.colours;
|
||||
|
@ -232,24 +269,16 @@ Image::~Image() {
|
|||
/* Should be called as part of program shutdown to free everything */
|
||||
void Image::Deinitialise() {
|
||||
if ( !initialised ) return;
|
||||
/*
|
||||
delete[] y_table;
|
||||
delete[] uv_table;
|
||||
delete[] r_v_table;
|
||||
delete[] g_v_table;
|
||||
delete[] g_u_table;
|
||||
delete[] b_u_table;
|
||||
*/
|
||||
initialised = false;
|
||||
if ( readjpg_dcinfo ) {
|
||||
jpeg_destroy_decompress(readjpg_dcinfo);
|
||||
delete readjpg_dcinfo;
|
||||
readjpg_dcinfo = 0;
|
||||
readjpg_dcinfo = NULL;
|
||||
}
|
||||
if ( decodejpg_dcinfo ) {
|
||||
jpeg_destroy_decompress(decodejpg_dcinfo);
|
||||
delete decodejpg_dcinfo;
|
||||
decodejpg_dcinfo = 0;
|
||||
decodejpg_dcinfo = NULL;
|
||||
}
|
||||
for ( unsigned int quality=0; quality <= 100; quality += 1 ) {
|
||||
if ( writejpg_ccinfo[quality] ) {
|
||||
|
@ -268,7 +297,7 @@ void Image::Deinitialise() {
|
|||
void Image::Initialise() {
|
||||
/* Assign the blend pointer to function */
|
||||
if ( config.fast_image_blends ) {
|
||||
if ( config.cpu_extensions && sseversion >= 20 ) {
|
||||
if ( config.cpu_extensions && sse_version >= 20 ) {
|
||||
fptr_blend = &sse2_fastblend; /* SSE2 fast blend */
|
||||
Debug(4, "Blend: Using SSE2 fast blend function");
|
||||
} else if ( config.cpu_extensions && neonversion >= 1 ) {
|
||||
|
@ -325,7 +354,7 @@ void Image::Initialise() {
|
|||
|
||||
/* Assign the delta functions */
|
||||
if ( config.cpu_extensions ) {
|
||||
if ( sseversion >= 35 ) {
|
||||
if ( sse_version >= 35 ) {
|
||||
/* SSSE3 available */
|
||||
fptr_delta8_rgba = &ssse3_delta8_rgba;
|
||||
fptr_delta8_bgra = &ssse3_delta8_bgra;
|
||||
|
@ -333,7 +362,7 @@ void Image::Initialise() {
|
|||
fptr_delta8_abgr = &ssse3_delta8_abgr;
|
||||
fptr_delta8_gray8 = &sse2_delta8_gray8;
|
||||
Debug(4, "Delta: Using SSSE3 delta functions");
|
||||
} else if ( sseversion >= 20 ) {
|
||||
} else if ( sse_version >= 20 ) {
|
||||
/* SSE2 available */
|
||||
fptr_delta8_rgba = &sse2_delta8_rgba;
|
||||
fptr_delta8_bgra = &sse2_delta8_bgra;
|
||||
|
@ -437,7 +466,7 @@ void Image::Initialise() {
|
|||
|
||||
#if defined(__i386__) && !defined(__x86_64__)
|
||||
/* Use SSE2 aligned memory copy? */
|
||||
if ( config.cpu_extensions && sseversion >= 20 ) {
|
||||
if ( config.cpu_extensions && sse_version >= 20 ) {
|
||||
fptr_imgbufcpy = &sse2_aligned_memcpy;
|
||||
Debug(4, "Image buffer copy: Using SSE2 aligned memcpy");
|
||||
} else {
|
||||
|
@ -449,60 +478,28 @@ void Image::Initialise() {
|
|||
Debug(4, "Image buffer copy: Using standard memcpy");
|
||||
#endif
|
||||
|
||||
/* Code below relocated from zm_local_camera */
|
||||
Debug( 3, "Setting up static colour tables" );
|
||||
|
||||
y_table = y_table_global;
|
||||
uv_table = uv_table_global;
|
||||
r_v_table = r_v_table_global;
|
||||
g_v_table = g_v_table_global;
|
||||
g_u_table = g_u_table_global;
|
||||
b_u_table = b_u_table_global;
|
||||
/*
|
||||
y_table = new unsigned char[256];
|
||||
for ( int i = 0; i <= 255; i++ )
|
||||
{
|
||||
unsigned char c = i;
|
||||
if ( c <= 16 )
|
||||
y_table[c] = 0;
|
||||
else if ( c >= 235 )
|
||||
y_table[c] = 255;
|
||||
else
|
||||
y_table[c] = (255*(c-16))/219;
|
||||
}
|
||||
|
||||
uv_table = new signed char[256];
|
||||
for ( int i = 0; i <= 255; i++ )
|
||||
{
|
||||
unsigned char c = i;
|
||||
if ( c <= 16 )
|
||||
uv_table[c] = -127;
|
||||
else if ( c >= 240 )
|
||||
uv_table[c] = 127;
|
||||
else
|
||||
uv_table[c] = (127*(c-128))/112;
|
||||
}
|
||||
|
||||
r_v_table = new short[255];
|
||||
g_v_table = new short[255];
|
||||
g_u_table = new short[255];
|
||||
b_u_table = new short[255];
|
||||
for ( int i = 0; i < 255; i++ )
|
||||
{
|
||||
r_v_table[i] = (1402*(i-128))/1000;
|
||||
g_u_table[i] = (344*(i-128))/1000;
|
||||
g_v_table[i] = (714*(i-128))/1000;
|
||||
b_u_table[i] = (1772*(i-128))/1000;
|
||||
}
|
||||
*/
|
||||
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
/* Requests a writeable buffer to the image. This is safer than buffer() because this way we can guarantee that a buffer of required size exists */
|
||||
uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder) {
|
||||
uint8_t* Image::WriteBuffer(
|
||||
const unsigned int p_width,
|
||||
const unsigned int p_height,
|
||||
const unsigned int p_colours,
|
||||
const unsigned int p_subpixelorder) {
|
||||
|
||||
if ( p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32 ) {
|
||||
if ( p_colours != ZM_COLOUR_GRAY8
|
||||
&&
|
||||
p_colours != ZM_COLOUR_RGB24
|
||||
&&
|
||||
p_colours != ZM_COLOUR_RGB32 ) {
|
||||
Error("WriteBuffer called with unexpected colours: %d", p_colours);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -513,6 +510,7 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
|
|||
}
|
||||
|
||||
if ( p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder ) {
|
||||
|
||||
unsigned int newsize = (p_width * p_height) * p_colours;
|
||||
|
||||
if ( buffer == NULL ) {
|
||||
|
@ -533,6 +531,7 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
|
|||
width = p_width;
|
||||
height = p_height;
|
||||
colours = p_colours;
|
||||
linesize = p_width * p_colours;
|
||||
subpixelorder = p_subpixelorder;
|
||||
pixels = height*width;
|
||||
size = newsize;
|
||||
|
@ -541,8 +540,18 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
|
|||
return buffer;
|
||||
}
|
||||
|
||||
/* Assign an existing buffer to the image instead of copying from a source buffer. The goal is to reduce the amount of memory copying and increase efficiency and buffer reusing. */
|
||||
void Image::AssignDirect( const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, uint8_t *new_buffer, const size_t buffer_size, const int p_buffertype) {
|
||||
/* Assign an existing buffer to the image instead of copying from a source buffer.
|
||||
The goal is to reduce the amount of memory copying and increase efficiency and buffer reusing.
|
||||
*/
|
||||
void Image::AssignDirect(
|
||||
const unsigned int p_width,
|
||||
const unsigned int p_height,
|
||||
const unsigned int p_colours,
|
||||
const unsigned int p_subpixelorder,
|
||||
uint8_t *new_buffer,
|
||||
const size_t buffer_size,
|
||||
const int p_buffertype) {
|
||||
|
||||
if ( new_buffer == NULL ) {
|
||||
Error("Attempt to directly assign buffer from a NULL pointer");
|
||||
return;
|
||||
|
@ -561,7 +570,8 @@ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_heigh
|
|||
unsigned int new_buffer_size = ((p_width*p_height)*p_colours);
|
||||
|
||||
if ( buffer_size < new_buffer_size ) {
|
||||
Error("Attempt to directly assign buffer from an undersized buffer of size: %zu, needed %dx%d*%d colours = %zu",buffer_size, p_width, p_height, p_colours, new_buffer_size );
|
||||
Error("Attempt to directly assign buffer from an undersized buffer of size: %zu, needed %dx%d*%d colours = %zu",
|
||||
buffer_size, p_width, p_height, p_colours, new_buffer_size);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -573,13 +583,15 @@ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_heigh
|
|||
width = p_width;
|
||||
height = p_height;
|
||||
colours = p_colours;
|
||||
linesize = width * colours;
|
||||
subpixelorder = p_subpixelorder;
|
||||
pixels = height*width;
|
||||
size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size
|
||||
|
||||
/* Copy into the held buffer */
|
||||
if ( new_buffer != buffer )
|
||||
if ( new_buffer != buffer ) {
|
||||
(*fptr_imgbufcpy)(buffer, new_buffer, size);
|
||||
}
|
||||
|
||||
/* Free the new buffer */
|
||||
DumpBuffer(new_buffer, p_buffertype);
|
||||
|
@ -591,6 +603,7 @@ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_heigh
|
|||
width = p_width;
|
||||
height = p_height;
|
||||
colours = p_colours;
|
||||
linesize = width*colours;
|
||||
subpixelorder = p_subpixelorder;
|
||||
pixels = height*width;
|
||||
size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size
|
||||
|
@ -599,10 +612,15 @@ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_heigh
|
|||
buffertype = p_buffertype;
|
||||
buffer = new_buffer;
|
||||
}
|
||||
} // end void Image::AssignDirect
|
||||
|
||||
}
|
||||
|
||||
void Image::Assign(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size) {
|
||||
void Image::Assign(
|
||||
const unsigned int p_width,
|
||||
const unsigned int p_height,
|
||||
const unsigned int p_colours,
|
||||
const unsigned int p_subpixelorder,
|
||||
const uint8_t* new_buffer,
|
||||
const size_t buffer_size) {
|
||||
unsigned int new_size = (p_width * p_height) * p_colours;
|
||||
|
||||
if ( new_buffer == NULL ) {
|
||||
|
@ -649,24 +667,30 @@ void Image::Assign(const unsigned int p_width, const unsigned int p_height, cons
|
|||
|
||||
if ( new_buffer != buffer )
|
||||
(*fptr_imgbufcpy)(buffer, new_buffer, size);
|
||||
|
||||
}
|
||||
|
||||
void Image::Assign(const Image &image) {
|
||||
unsigned int new_size = (image.width * image.height) * image.colours;
|
||||
unsigned int new_size = image.height * image.linesize;
|
||||
|
||||
if ( image.buffer == NULL ) {
|
||||
Error("Attempt to assign image with an empty buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( image.colours != ZM_COLOUR_GRAY8 && image.colours != ZM_COLOUR_RGB24 && image.colours != ZM_COLOUR_RGB32 ) {
|
||||
if ( image.colours != ZM_COLOUR_GRAY8
|
||||
&&
|
||||
image.colours != ZM_COLOUR_RGB24
|
||||
&&
|
||||
image.colours != ZM_COLOUR_RGB32 ) {
|
||||
Error("Attempt to assign image with unexpected colours per pixel: %d", image.colours);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !buffer || image.width != width || image.height != height
|
||||
|| image.colours != colours || image.subpixelorder != subpixelorder) {
|
||||
if ( !buffer
|
||||
|| image.width != width || image.height != height
|
||||
|| image.colours != colours || image.subpixelorder != subpixelorder
|
||||
|| image.linesize != linesize
|
||||
) {
|
||||
|
||||
if ( holdbuffer && buffer ) {
|
||||
if ( new_size > allocation ) {
|
||||
|
@ -686,13 +710,19 @@ void Image::Assign( const Image &image ) {
|
|||
colours = image.colours;
|
||||
subpixelorder = image.subpixelorder;
|
||||
size = new_size;
|
||||
linesize = image.linesize;
|
||||
}
|
||||
|
||||
if ( image.buffer != buffer )
|
||||
(*fptr_imgbufcpy)(buffer, image.buffer, size);
|
||||
}
|
||||
|
||||
Image *Image::HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p_subpixelorder, const Box *limits ) {
|
||||
Image *Image::HighlightEdges(
|
||||
Rgb colour,
|
||||
unsigned int p_colours,
|
||||
unsigned int p_subpixelorder,
|
||||
const Box *limits
|
||||
) {
|
||||
if ( colours != ZM_COLOUR_GRAY8 ) {
|
||||
Panic("Attempt to highlight image edges when colours = %d", colours);
|
||||
}
|
||||
|
@ -712,79 +742,71 @@ Image *Image::HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p
|
|||
unsigned int hi_x = limits ? limits->Hi().X() : width-1;
|
||||
unsigned int hi_y = limits ? limits->Hi().Y() : height-1;
|
||||
|
||||
if ( p_colours == ZM_COLOUR_GRAY8 )
|
||||
{
|
||||
for ( unsigned int y = lo_y; y <= hi_y; y++ )
|
||||
{
|
||||
const uint8_t* p = buffer + (y * width) + lo_x;
|
||||
uint8_t* phigh = high_buff + (y * width) + lo_x;
|
||||
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ )
|
||||
{
|
||||
if ( p_colours == ZM_COLOUR_GRAY8 ) {
|
||||
for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
|
||||
const uint8_t* p = buffer + (y * linesize) + lo_x;
|
||||
uint8_t* phigh = high_buff + (y * linesize) + lo_x;
|
||||
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) {
|
||||
bool edge = false;
|
||||
if ( *p )
|
||||
{
|
||||
if ( *p ) {
|
||||
edge = (x > 0 && !*(p-1)) || (x < (width-1) && !*(p+1)) || (y > 0 && !*(p-width)) || (y < (height-1) && !*(p+width));
|
||||
#if 0
|
||||
if ( !edge && x > 0 && !*(p-1) ) edge = true;
|
||||
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
|
||||
if ( !edge && y > 0 && !*(p-width) ) edge = true;
|
||||
if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
|
||||
#endif
|
||||
}
|
||||
if ( edge )
|
||||
{
|
||||
if ( edge ) {
|
||||
*phigh = colour;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( p_colours == ZM_COLOUR_RGB24 )
|
||||
{
|
||||
for ( unsigned int y = lo_y; y <= hi_y; y++ )
|
||||
{
|
||||
const uint8_t* p = buffer + (y * width) + lo_x;
|
||||
uint8_t* phigh = high_buff + (((y * width) + lo_x) * 3);
|
||||
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh += 3 )
|
||||
{
|
||||
} else if ( p_colours == ZM_COLOUR_RGB24 ) {
|
||||
for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
|
||||
const uint8_t* p = buffer + (y * linesize) + lo_x;
|
||||
uint8_t* phigh = high_buff + (((y * linesize) + lo_x) * 3);
|
||||
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh += 3 ) {
|
||||
bool edge = false;
|
||||
if ( *p )
|
||||
{
|
||||
if ( *p ) {
|
||||
edge = (x > 0 && !*(p-1)) || (x < (width-1) && !*(p+1)) || (y > 0 && !*(p-width)) || (y < (height-1) && !*(p+width));
|
||||
#if 0
|
||||
if ( !edge && x > 0 && !*(p-1) ) edge = true;
|
||||
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
|
||||
if ( !edge && y > 0 && !*(p-width) ) edge = true;
|
||||
if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
|
||||
#endif
|
||||
}
|
||||
if ( edge )
|
||||
{
|
||||
if ( edge ) {
|
||||
RED_PTR_RGBA(phigh) = RED_VAL_RGBA(colour);
|
||||
GREEN_PTR_RGBA(phigh) = GREEN_VAL_RGBA(colour);
|
||||
BLUE_PTR_RGBA(phigh) = BLUE_VAL_RGBA(colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( p_colours == ZM_COLOUR_RGB32 )
|
||||
{
|
||||
for ( unsigned int y = lo_y; y <= hi_y; y++ )
|
||||
{
|
||||
const uint8_t* p = buffer + (y * width) + lo_x;
|
||||
Rgb* phigh = (Rgb*)(high_buff + (((y * width) + lo_x) * 4));
|
||||
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ )
|
||||
{
|
||||
} else if ( p_colours == ZM_COLOUR_RGB32 ) {
|
||||
for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
|
||||
const uint8_t* p = buffer + (y * linesize) + lo_x;
|
||||
Rgb* phigh = (Rgb*)(high_buff + (((y * linesize) + lo_x) * 4));
|
||||
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) {
|
||||
bool edge = false;
|
||||
if ( *p )
|
||||
{
|
||||
if ( *p ) {
|
||||
edge = (x > 0 && !*(p-1)) || (x < (width-1) && !*(p+1)) || (y > 0 && !*(p-width)) || (y < (height-1) && !*(p+width));
|
||||
#if 0
|
||||
if ( !edge && x > 0 && !*(p-1) ) edge = true;
|
||||
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
|
||||
if ( !edge && y > 0 && !*(p-width) ) edge = true;
|
||||
if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
|
||||
#endif
|
||||
}
|
||||
if ( edge )
|
||||
{
|
||||
if ( edge ) {
|
||||
*phigh = colour;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return( high_image );
|
||||
return high_image;
|
||||
}
|
||||
|
||||
bool Image::ReadRaw(const char *filename) {
|
||||
|
@ -886,14 +908,11 @@ bool Image::ReadJpeg(const char *filename, unsigned int p_colours, unsigned int
|
|||
|
||||
switch ( p_colours ) {
|
||||
case ZM_COLOUR_GRAY8:
|
||||
{
|
||||
cinfo->out_color_space = JCS_GRAYSCALE;
|
||||
new_colours = ZM_COLOUR_GRAY8;
|
||||
new_subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
break;
|
||||
}
|
||||
case ZM_COLOUR_RGB32:
|
||||
{
|
||||
#ifdef JCS_EXTENSIONS
|
||||
new_colours = ZM_COLOUR_RGB32;
|
||||
if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
|
||||
|
@ -914,10 +933,8 @@ bool Image::ReadJpeg(const char *filename, unsigned int p_colours, unsigned int
|
|||
#else
|
||||
Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead.");
|
||||
#endif
|
||||
}
|
||||
case ZM_COLOUR_RGB24:
|
||||
default:
|
||||
{
|
||||
new_colours = ZM_COLOUR_RGB24;
|
||||
if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGR ) {
|
||||
#ifdef JCS_EXTENSIONS
|
||||
|
@ -941,8 +958,7 @@ cinfo->out_color_space = JCS_RGB;
|
|||
new_subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // end switch p_colours
|
||||
|
||||
if ( WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL ) {
|
||||
Error("Failed requesting writeable buffer for reading JPEG image.");
|
||||
|
@ -953,11 +969,10 @@ cinfo->out_color_space = JCS_RGB;
|
|||
|
||||
jpeg_start_decompress(cinfo);
|
||||
|
||||
JSAMPROW row_pointer; /* pointer to a single row */
|
||||
int row_stride = width * colours; /* physical row width in buffer */
|
||||
JSAMPROW row_pointer = buffer;
|
||||
while ( cinfo->output_scanline < cinfo->output_height ) {
|
||||
row_pointer = &buffer[cinfo->output_scanline * row_stride];
|
||||
jpeg_read_scanlines(cinfo, &row_pointer, 1);
|
||||
row_pointer += linesize;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(cinfo);
|
||||
|
@ -971,21 +986,22 @@ cinfo->out_color_space = JCS_RGB;
|
|||
// Note quality=zero means default
|
||||
|
||||
bool Image::WriteJpeg(const char *filename, int quality_override) const {
|
||||
return Image::WriteJpeg(filename, quality_override, (timeval){0,0});
|
||||
return Image::WriteJpeg(filename, quality_override, (timeval){0,0}, false);
|
||||
}
|
||||
bool Image::WriteJpeg(const char *filename) const {
|
||||
return Image::WriteJpeg(filename, 0, (timeval){0,0});
|
||||
return Image::WriteJpeg(filename, 0, (timeval){0,0}, false);
|
||||
}
|
||||
bool Image::WriteJpeg(const char *filename, bool on_blocking_abort) const {
|
||||
return Image::WriteJpeg(filename, 0, (timeval){0,0}, on_blocking_abort);
|
||||
}
|
||||
bool Image::WriteJpeg(const char *filename, struct timeval timestamp) const {
|
||||
return Image::WriteJpeg(filename, 0, timestamp);
|
||||
return Image::WriteJpeg(filename, 0, timestamp, false);
|
||||
}
|
||||
|
||||
bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval timestamp) const {
|
||||
return Image::WriteJpeg(filename, quality_override, timestamp, false);
|
||||
}
|
||||
|
||||
bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval timestamp, bool on_blocking_abort) const {
|
||||
if ( config.colour_jpeg_files && (colours == ZM_COLOUR_GRAY8) ) {
|
||||
Image temp_image(*this);
|
||||
|
@ -997,14 +1013,12 @@ bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval
|
|||
struct jpeg_compress_struct *cinfo = writejpg_ccinfo[quality];
|
||||
FILE *outfile = NULL;
|
||||
static int raw_fd = 0;
|
||||
bool need_create_comp = false;
|
||||
raw_fd = 0;
|
||||
|
||||
if ( !cinfo ) {
|
||||
cinfo = writejpg_ccinfo[quality] = new jpeg_compress_struct;
|
||||
cinfo->err = jpeg_std_error(&jpg_err.pub);
|
||||
jpeg_create_compress(cinfo);
|
||||
need_create_comp = true;
|
||||
}
|
||||
if ( !on_blocking_abort ) {
|
||||
jpg_err.pub.error_exit = zm_jpeg_error_exit;
|
||||
|
@ -1022,8 +1036,6 @@ bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval
|
|||
return false;
|
||||
}
|
||||
}
|
||||
if ( need_create_comp )
|
||||
jpeg_create_compress(cinfo);
|
||||
|
||||
if ( !on_blocking_abort ) {
|
||||
if ( (outfile = fopen(filename, "wb")) == NULL ) {
|
||||
|
@ -1054,13 +1066,16 @@ bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval
|
|||
case ZM_COLOUR_RGB32:
|
||||
#ifdef JCS_EXTENSIONS
|
||||
cinfo->input_components = 4;
|
||||
if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
|
||||
if ( subpixelorder == ZM_SUBPIX_ORDER_RGBA ) {
|
||||
cinfo->in_color_space = JCS_EXT_RGBX;
|
||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
|
||||
cinfo->in_color_space = JCS_EXT_BGRX;
|
||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) {
|
||||
cinfo->in_color_space = JCS_EXT_XRGB;
|
||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) {
|
||||
cinfo->in_color_space = JCS_EXT_XBGR;
|
||||
} else {
|
||||
Warning("Unknwon subpixelorder %d", subpixelorder);
|
||||
/* Assume RGBA */
|
||||
cinfo->in_color_space = JCS_EXT_RGBX;
|
||||
}
|
||||
|
@ -1130,15 +1145,12 @@ cinfo->out_color_space = JCS_RGB;
|
|||
jpeg_write_marker(cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes));
|
||||
}
|
||||
|
||||
JSAMPROW row_pointer; /* pointer to a single row */
|
||||
int row_stride = cinfo->image_width * colours; /* physical row width in buffer */
|
||||
JSAMPROW row_pointer = buffer; /* pointer to a single row */
|
||||
while ( cinfo->next_scanline < cinfo->image_height ) {
|
||||
row_pointer = &buffer[cinfo->next_scanline * row_stride];
|
||||
jpeg_write_scanlines(cinfo, &row_pointer, 1);
|
||||
row_pointer += linesize;
|
||||
}
|
||||
|
||||
jpeg_finish_compress(cinfo);
|
||||
|
||||
fclose(outfile);
|
||||
|
||||
return true;
|
||||
|
@ -1252,11 +1264,10 @@ cinfo->out_color_space = JCS_RGB;
|
|||
|
||||
jpeg_start_decompress(cinfo);
|
||||
|
||||
JSAMPROW row_pointer; /* pointer to a single row */
|
||||
int row_stride = width * colours; /* physical row width in buffer */
|
||||
JSAMPROW row_pointer = buffer; /* pointer to a single row */
|
||||
while ( cinfo->output_scanline < cinfo->output_height ) {
|
||||
row_pointer = &buffer[cinfo->output_scanline * row_stride];
|
||||
jpeg_read_scanlines(cinfo, &row_pointer, 1);
|
||||
row_pointer += linesize;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(cinfo);
|
||||
|
@ -1296,13 +1307,16 @@ bool Image::EncodeJpeg(JOCTET *outbuffer, int *outbuffer_size, int quality_overr
|
|||
case ZM_COLOUR_RGB32:
|
||||
#ifdef JCS_EXTENSIONS
|
||||
cinfo->input_components = 4;
|
||||
if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
|
||||
if ( subpixelorder == ZM_SUBPIX_ORDER_RGBA ) {
|
||||
cinfo->in_color_space = JCS_EXT_RGBX;
|
||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
|
||||
cinfo->in_color_space = JCS_EXT_BGRX;
|
||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) {
|
||||
cinfo->in_color_space = JCS_EXT_XRGB;
|
||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) {
|
||||
cinfo->in_color_space = JCS_EXT_XBGR;
|
||||
} else {
|
||||
Warning("unknown subpixelorder %d", subpixelorder);
|
||||
/* Assume RGBA */
|
||||
cinfo->in_color_space = JCS_EXT_RGBX;
|
||||
}
|
||||
|
@ -1343,11 +1357,10 @@ cinfo->out_color_space = JCS_RGB;
|
|||
|
||||
jpeg_start_compress(cinfo, TRUE);
|
||||
|
||||
JSAMPROW row_pointer; /* pointer to a single row */
|
||||
int row_stride = cinfo->image_width * colours; /* physical row width in buffer */
|
||||
JSAMPROW row_pointer = buffer;
|
||||
while ( cinfo->next_scanline < cinfo->image_height ) {
|
||||
row_pointer = &buffer[cinfo->next_scanline * row_stride];
|
||||
jpeg_write_scanlines(cinfo, &row_pointer, 1);
|
||||
row_pointer += linesize;
|
||||
}
|
||||
|
||||
jpeg_finish_compress(cinfo);
|
||||
|
@ -1386,10 +1399,11 @@ bool Image::Crop( unsigned int lo_x, unsigned int lo_y, unsigned int hi_x, unsig
|
|||
|
||||
if ( lo_x > hi_x || lo_y > hi_y ) {
|
||||
Error("Invalid or reversed crop region %d,%d -> %d,%d", lo_x, lo_y, hi_x, hi_y);
|
||||
return( false );
|
||||
return false;
|
||||
}
|
||||
if ( hi_x > (width-1) || ( hi_y > (height-1) ) ) {
|
||||
Error( "Attempting to crop outside image, %d,%d -> %d,%d not in %d,%d", lo_x, lo_y, hi_x, hi_y, width-1, height-1 );
|
||||
Error("Attempting to crop outside image, %d,%d -> %d,%d not in %d,%d",
|
||||
lo_x, lo_y, hi_x, hi_y, width-1, height-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1402,7 +1416,7 @@ bool Image::Crop( unsigned int lo_x, unsigned int lo_y, unsigned int hi_x, unsig
|
|||
|
||||
unsigned int new_stride = new_width * colours;
|
||||
for ( unsigned int y = lo_y, ny = 0; y <= hi_y; y++, ny++ ) {
|
||||
unsigned char *pbuf = &buffer[((y*width)+lo_x)*colours];
|
||||
unsigned char *pbuf = &buffer[((y*linesize)+lo_x)];
|
||||
unsigned char *pnbuf = &new_buffer[(ny*new_width)*colours];
|
||||
memcpy( pnbuf, pbuf, new_stride );
|
||||
}
|
||||
|
@ -1631,8 +1645,7 @@ void Image::Overlay( const Image &image, unsigned int x, unsigned int y ) {
|
|||
} else {
|
||||
Error("Overlay called with unexpected colours: %d", colours);
|
||||
}
|
||||
|
||||
}
|
||||
} // end void Image::Overlay( const Image &image, unsigned int x, unsigned int y )
|
||||
|
||||
void Image::Blend( const Image &image, int transparency ) {
|
||||
#ifdef ZM_IMAGE_PROFILING
|
||||
|
@ -1771,7 +1784,7 @@ Image *Image::Highlight( unsigned int n_images, Image *images[], const Rgb thres
|
|||
return result;
|
||||
}
|
||||
|
||||
/* New function to allow buffer re-using instead of allocationg memory for the delta image every time */
|
||||
/* New function to allow buffer re-using instead of allocating memory for the delta image every time */
|
||||
void Image::Delta( const Image &image, Image* targetimage) const {
|
||||
#ifdef ZM_IMAGE_PROFILING
|
||||
struct timespec start,end,diff;
|
||||
|
@ -1858,7 +1871,7 @@ const Coord Image::centreCoord( const char *text ) const {
|
|||
}
|
||||
int x = (width - (max_line_len * ZM_CHAR_WIDTH) ) / 2;
|
||||
int y = (height - (line_no * LINE_HEIGHT) ) / 2;
|
||||
return( Coord( x, y ) );
|
||||
return Coord(x, y);
|
||||
}
|
||||
|
||||
/* RGB32 compatible: complete */
|
||||
|
@ -1967,10 +1980,19 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
|||
unsigned char *temp_ptr = ptr;
|
||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||
int f;
|
||||
if (size == 2)
|
||||
if ( size == 2 ) {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
||||
else
|
||||
} else {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r];
|
||||
}
|
||||
for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) {
|
||||
if ( f & (zm_text_bitmask >> i) ) {
|
||||
if ( !fg_trans )
|
||||
|
@ -1989,10 +2011,19 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
|||
unsigned char *temp_ptr = ptr;
|
||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||
int f;
|
||||
if (size == 2)
|
||||
if ( size == 2 ) {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
||||
else
|
||||
} else {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r];
|
||||
}
|
||||
for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr += colours ) {
|
||||
if ( f & (zm_text_bitmask >> i) ) {
|
||||
if ( !fg_trans ) {
|
||||
|
@ -2016,10 +2047,19 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
|||
Rgb* temp_ptr = (Rgb*)ptr;
|
||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||
int f;
|
||||
if (size == 2)
|
||||
if ( size == 2 ) {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
||||
else
|
||||
} else {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r];
|
||||
}
|
||||
for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) {
|
||||
if ( f & (zm_text_bitmask >> i) ) {
|
||||
if ( !fg_trans ) {
|
||||
|
@ -2033,7 +2073,7 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
|||
}
|
||||
|
||||
} else {
|
||||
Panic("Annotate called with unexpected colours: %d",colours);
|
||||
Error("Annotate called with unexpected colours: %d", colours);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2123,7 +2163,7 @@ void Image::DeColourise() {
|
|||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
size = width * height;
|
||||
|
||||
if ( colours == ZM_COLOUR_RGB32 && config.cpu_extensions && sseversion >= 35 ) {
|
||||
if ( colours == ZM_COLOUR_RGB32 && config.cpu_extensions && sse_version >= 35 ) {
|
||||
/* Use SSSE3 functions */
|
||||
switch (subpixelorder) {
|
||||
case ZM_SUBPIX_ORDER_BGRA:
|
||||
|
@ -2317,9 +2357,7 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) {
|
|||
|
||||
double grad;
|
||||
|
||||
//Debug( 9, "dx: %.2lf, dy: %.2lf", dx, dy );
|
||||
if ( fabs(dx) <= fabs(dy) ) {
|
||||
//Debug( 9, "dx <= dy" );
|
||||
if ( y1 != y2 )
|
||||
grad = dx/dy;
|
||||
else
|
||||
|
@ -2329,9 +2367,7 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) {
|
|||
int y, yinc = (y1<y2)?1:-1;
|
||||
grad *= yinc;
|
||||
if ( colours == ZM_COLOUR_GRAY8 ) {
|
||||
//Debug( 9, "x1:%d, x2:%d, y1:%d, y2:%d, gr:%.2f", x1, x2, y1, y2, grad );
|
||||
for ( x = x1, y = y1; y != y2; y += yinc, x += grad ) {
|
||||
//Debug( 9, "x:%.2f, y:%d", x, y );
|
||||
buffer[(y*width)+int(round(x))] = colour;
|
||||
}
|
||||
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
||||
|
@ -2418,7 +2454,8 @@ void Image::Fill( Rgb colour, int density, const Polygon &polygon ) {
|
|||
#ifndef ZM_DBG_OFF
|
||||
if ( logLevel() >= Logger::DEBUG9 ) {
|
||||
for ( int i = 0; i < n_global_edges; i++ ) {
|
||||
Debug( 9, "%d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", i, global_edges[i].min_y, global_edges[i].max_y, global_edges[i].min_x, global_edges[i]._1_m );
|
||||
Debug(9, "%d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f",
|
||||
i, global_edges[i].min_y, global_edges[i].max_y, global_edges[i].min_x, global_edges[i]._1_m);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -2445,7 +2482,8 @@ void Image::Fill( Rgb colour, int density, const Polygon &polygon ) {
|
|||
#ifndef ZM_DBG_OFF
|
||||
if ( logLevel() >= Logger::DEBUG9 ) {
|
||||
for ( int i = 0; i < n_active_edges; i++ ) {
|
||||
Debug( 9, "%d - %d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", y, i, active_edges[i].min_y, active_edges[i].max_y, active_edges[i].min_x, active_edges[i]._1_m );
|
||||
Debug(9, "%d - %d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f",
|
||||
y, i, active_edges[i].min_y, active_edges[i].max_y, active_edges[i].min_x, active_edges[i]._1_m );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -2503,18 +2541,12 @@ void Image::Fill( Rgb colour, const Polygon &polygon ) {
|
|||
Fill(colour, 1, polygon);
|
||||
}
|
||||
|
||||
/* RGB32 compatible: complete */
|
||||
void Image::Rotate(int angle) {
|
||||
|
||||
angle %= 360;
|
||||
|
||||
if ( !angle ) {
|
||||
if ( !angle || angle%90 ) {
|
||||
return;
|
||||
}
|
||||
if ( angle%90 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int new_height = height;
|
||||
unsigned int new_width = width;
|
||||
uint8_t* rotate_buffer = AllocBuffer(size);
|
||||
|
@ -2538,17 +2570,17 @@ void Image::Rotate( int angle ) {
|
|||
}
|
||||
} else if ( colours == ZM_COLOUR_RGB32 ) {
|
||||
Rgb* s_rptr = (Rgb*)s_ptr;
|
||||
for ( unsigned int i = new_width; i > 0; i-- ) {
|
||||
for ( unsigned int i = new_width; i; i-- ) {
|
||||
Rgb* d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
|
||||
for ( unsigned int j = new_height; j > 0; j-- ) {
|
||||
for ( unsigned int j = new_height; j; j-- ) {
|
||||
*d_rptr = *s_rptr++;
|
||||
d_rptr += new_width;
|
||||
}
|
||||
}
|
||||
} else /* Assume RGB24 */ {
|
||||
for ( unsigned int i = new_width; i > 0; i-- ) {
|
||||
for ( unsigned int i = new_width; i; i-- ) {
|
||||
unsigned char *d_ptr = rotate_buffer+((i-1)*3);
|
||||
for ( unsigned int j = new_height; j > 0; j-- ) {
|
||||
for ( unsigned int j = new_height; j; j-- ) {
|
||||
*d_ptr = *s_ptr++;
|
||||
*(d_ptr+1) = *s_ptr++;
|
||||
*(d_ptr+2) = *s_ptr++;
|
||||
|
@ -2628,7 +2660,7 @@ void Image::Rotate( int angle ) {
|
|||
}
|
||||
|
||||
AssignDirect(new_width, new_height, colours, subpixelorder, rotate_buffer, size, ZM_BUFTYPE_ZM);
|
||||
}
|
||||
} // void Image::Rotate(int angle)
|
||||
|
||||
/* RGB32 compatible: complete */
|
||||
void Image::Flip( bool leftright ) {
|
||||
|
@ -2685,7 +2717,6 @@ void Image::Flip( bool leftright ) {
|
|||
}
|
||||
|
||||
AssignDirect(width, height, colours, subpixelorder, flip_buffer, size, ZM_BUFTYPE_ZM);
|
||||
|
||||
}
|
||||
|
||||
void Image::Scale(unsigned int factor) {
|
||||
|
@ -2700,6 +2731,7 @@ void Image::Scale( unsigned int factor ) {
|
|||
unsigned int new_width = (width*factor)/ZM_SCALE_BASE;
|
||||
unsigned int new_height = (height*factor)/ZM_SCALE_BASE;
|
||||
|
||||
// Why larger than we need?
|
||||
size_t scale_buffer_size = (new_width+1) * (new_height+1) * colours;
|
||||
|
||||
uint8_t* scale_buffer = AllocBuffer(scale_buffer_size);
|
||||
|
@ -2747,7 +2779,7 @@ void Image::Scale( unsigned int factor ) {
|
|||
unsigned int last_h_index = 0;
|
||||
unsigned int last_w_index = 0;
|
||||
unsigned int h_index;
|
||||
for ( unsigned int y = 0; y < (unsigned int)height; y++ ) {
|
||||
for ( unsigned int y = 0; y < height; y++ ) {
|
||||
h_count += factor;
|
||||
h_index = h_count/ZM_SCALE_BASE;
|
||||
if ( h_index > last_h_index ) {
|
||||
|
@ -2756,7 +2788,7 @@ void Image::Scale( unsigned int factor ) {
|
|||
last_w_index = 0;
|
||||
|
||||
unsigned char *ps = &buffer[y*wc];
|
||||
for ( unsigned int x = 0; x < (unsigned int)width; x++ ) {
|
||||
for ( unsigned int x = 0; x < width; x++ ) {
|
||||
w_count += factor;
|
||||
w_index = w_count/ZM_SCALE_BASE;
|
||||
|
||||
|
@ -2774,10 +2806,8 @@ void Image::Scale( unsigned int factor ) {
|
|||
}
|
||||
new_width = last_w_index;
|
||||
new_height = last_h_index;
|
||||
}
|
||||
|
||||
} // end foreach line
|
||||
AssignDirect(new_width, new_height, colours, subpixelorder, scale_buffer, scale_buffer_size, ZM_BUFTYPE_ZM);
|
||||
|
||||
}
|
||||
|
||||
void Image::Deinterlace_Discard() {
|
||||
|
@ -2818,7 +2848,6 @@ void Image::Deinterlace_Discard() {
|
|||
} else {
|
||||
Error("Deinterlace called with unexpected colours: %d", colours);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Image::Deinterlace_Linear() {
|
||||
|
@ -3619,6 +3648,7 @@ __attribute__((noinline)) void fast_delta8_argb(const uint8_t* col1, const uint8
|
|||
result += 4;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((noinline)) void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) {
|
||||
/* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */
|
||||
int r,g,b;
|
||||
|
|
|
@ -152,9 +152,11 @@ protected:
|
|||
static struct zm_error_mgr jpg_err;
|
||||
|
||||
unsigned int width;
|
||||
unsigned int linesize;
|
||||
unsigned int height;
|
||||
unsigned int pixels;
|
||||
unsigned int colours;
|
||||
unsigned int padding;
|
||||
unsigned int size;
|
||||
unsigned int subpixelorder;
|
||||
unsigned long allocation;
|
||||
|
@ -166,14 +168,17 @@ protected:
|
|||
public:
|
||||
Image();
|
||||
explicit Image(const char *filename);
|
||||
Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0);
|
||||
Image(int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0, unsigned int padding=0);
|
||||
Image(int p_width, int p_linesize, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0, unsigned int padding=0);
|
||||
explicit Image( const Image &p_image );
|
||||
explicit Image( const AVFrame *frame );
|
||||
|
||||
~Image();
|
||||
static void Initialise();
|
||||
static void Deinitialise();
|
||||
|
||||
inline unsigned int Width() const { return width; }
|
||||
inline unsigned int LineSize() const { return linesize; }
|
||||
inline unsigned int Height() const { return height; }
|
||||
inline unsigned int Pixels() const { return pixels; }
|
||||
inline unsigned int Colours() const { return colours; }
|
||||
|
@ -182,7 +187,7 @@ public:
|
|||
|
||||
/* Internal buffer should not be modified from functions outside of this class */
|
||||
inline const uint8_t* Buffer() const { return buffer; }
|
||||
inline const uint8_t* Buffer( unsigned int x, unsigned int y= 0 ) const { return &buffer[colours*((y*width)+x)]; }
|
||||
inline const uint8_t* Buffer( unsigned int x, unsigned int y= 0 ) const { return &buffer[(y*linesize)+x]; }
|
||||
/* Request writeable buffer */
|
||||
uint8_t* WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder);
|
||||
|
||||
|
@ -193,12 +198,25 @@ public:
|
|||
if ( !holdbuffer )
|
||||
DumpImgBuffer();
|
||||
|
||||
width = height = colours = size = pixels = subpixelorder = 0;
|
||||
width = linesize = height = colours = size = pixels = subpixelorder = 0;
|
||||
}
|
||||
|
||||
void Assign( unsigned int p_width, unsigned int p_height, unsigned int p_colours, unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size);
|
||||
void Assign(
|
||||
unsigned int p_width,
|
||||
unsigned int p_height,
|
||||
unsigned int p_colours,
|
||||
unsigned int p_subpixelorder,
|
||||
const uint8_t* new_buffer,
|
||||
const size_t buffer_size);
|
||||
void Assign(const Image &image);
|
||||
void AssignDirect( const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, uint8_t *new_buffer, const size_t buffer_size, const int p_buffertype);
|
||||
void AssignDirect(
|
||||
const unsigned int p_width,
|
||||
const unsigned int p_height,
|
||||
const unsigned int p_colours,
|
||||
const unsigned int p_subpixelorder,
|
||||
uint8_t *new_buffer,
|
||||
const size_t buffer_size,
|
||||
const int p_buffertype);
|
||||
|
||||
inline void CopyBuffer(const Image &image) {
|
||||
Assign(image);
|
||||
|
|
|
@ -504,7 +504,7 @@ LocalCamera::LocalCamera(
|
|||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
} else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8 ) {
|
||||
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
|
||||
if ( config.cpu_extensions && sseversion >= 35 ) {
|
||||
if ( config.cpu_extensions && sse_version >= 35 ) {
|
||||
conversion_fptr = &ssse3_convert_yuyv_gray8;
|
||||
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
||||
} else {
|
||||
|
@ -616,7 +616,7 @@ LocalCamera::LocalCamera(
|
|||
}
|
||||
} else if ( (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_GRAY8 ) {
|
||||
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
|
||||
if ( config.cpu_extensions && sseversion >= 35 ) {
|
||||
if ( config.cpu_extensions && sse_version >= 35 ) {
|
||||
conversion_fptr = &ssse3_convert_yuyv_gray8;
|
||||
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
||||
} else {
|
||||
|
|
|
@ -131,7 +131,7 @@ Monitor::MonitorLink::~MonitorLink() {
|
|||
}
|
||||
|
||||
bool Monitor::MonitorLink::connect() {
|
||||
if ( !last_connect_time || (time( 0 ) - last_connect_time) > 60 ) {
|
||||
if ( !last_connect_time || (time( 0 ) - last_connect_time) > ZM_MAX_RESTART_DELAY ) {
|
||||
last_connect_time = time( 0 );
|
||||
|
||||
mem_size = sizeof(SharedData) + sizeof(TriggerData);
|
||||
|
@ -379,6 +379,7 @@ Monitor::Monitor(
|
|||
|
||||
strncpy(event_prefix, p_event_prefix, sizeof(event_prefix)-1);
|
||||
strncpy(label_format, p_label_format, sizeof(label_format)-1);
|
||||
Debug(1, "encoder params %s", encoderparams.c_str());
|
||||
|
||||
// Change \n to actual line feeds
|
||||
char *token_ptr = label_format;
|
||||
|
@ -531,6 +532,7 @@ Monitor::Monitor(
|
|||
shared_data->last_write_index, shared_data->last_write_time );
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(),
|
||||
image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize());
|
||||
adaptive_skip = true;
|
||||
|
@ -605,7 +607,7 @@ bool Monitor::connect() {
|
|||
if ( mem_ptr == MAP_FAILED )
|
||||
Fatal("Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno);
|
||||
if ( mem_ptr == NULL ) {
|
||||
Error("mmap gave a null address:");
|
||||
Error("mmap gave a NULL address:");
|
||||
} else {
|
||||
Debug(3, "mmapped to %p", mem_ptr);
|
||||
}
|
||||
|
@ -1406,9 +1408,6 @@ bool Monitor::Analyse() {
|
|||
score += trigger_data->trigger_score;
|
||||
Debug(1, "Triggered on score += %d => %d", trigger_data->trigger_score, score);
|
||||
if ( !event ) {
|
||||
// How could it have a length already?
|
||||
//if ( cause.length() )
|
||||
//cause += ", ";
|
||||
cause += trigger_data->trigger_cause;
|
||||
}
|
||||
Event::StringSet noteSet;
|
||||
|
@ -1488,6 +1487,7 @@ bool Monitor::Analyse() {
|
|||
score += 50;
|
||||
}
|
||||
} else {
|
||||
Debug(1, "Linked monitor %d %d is not connected. Connecting.", i, linked_monitors[i]->Id());
|
||||
linked_monitors[i]->connect();
|
||||
}
|
||||
} // end foreach linked_monit
|
||||
|
@ -1502,7 +1502,7 @@ bool Monitor::Analyse() {
|
|||
|
||||
if ( section_length
|
||||
&& ( ( timestamp->tv_sec - video_store_data->recording.tv_sec ) >= section_length )
|
||||
&& ( (event_close_mode != CLOSE_TIME) || ! ( timestamp->tv_sec % section_length ) )
|
||||
&& ( (function == MOCORD && (event_close_mode != CLOSE_TIME)) || ! ( timestamp->tv_sec % section_length ) )
|
||||
) {
|
||||
Info("%s: %03d - Closing event %" PRIu64 ", section end forced %d - %d = %d >= %d",
|
||||
name, image_count, event->Id(),
|
||||
|
@ -1515,7 +1515,6 @@ bool Monitor::Analyse() {
|
|||
} // end if event
|
||||
|
||||
if ( !event ) {
|
||||
|
||||
// Create event
|
||||
event = new Event(this, *timestamp, "Continuous", noteSetMap, videoRecording);
|
||||
shared_data->last_event = event->Id();
|
||||
|
@ -1529,7 +1528,6 @@ bool Monitor::Analyse() {
|
|||
if ( state == IDLE ) {
|
||||
shared_data->state = state = TAPE;
|
||||
}
|
||||
|
||||
} // end if ! event
|
||||
} // end if function == RECORD || function == MOCORD)
|
||||
} // end if !signal_change && signal
|
||||
|
@ -1553,7 +1551,6 @@ bool Monitor::Analyse() {
|
|||
);
|
||||
}
|
||||
if ( (!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count-1) ) {
|
||||
shared_data->state = state = ALARM;
|
||||
// lets construct alarm cause. It will contain cause + names of zones alarmed
|
||||
std::string alarm_cause = "";
|
||||
for ( int i=0; i < n_zones; i++ ) {
|
||||
|
@ -1638,6 +1635,7 @@ bool Monitor::Analyse() {
|
|||
event->SavePreAlarmFrames();
|
||||
}
|
||||
}
|
||||
shared_data->state = state = ALARM;
|
||||
} else if ( state != PREALARM ) {
|
||||
Info("%s: %03d - Gone into prealarm state", name, image_count);
|
||||
shared_data->state = state = PREALARM;
|
||||
|
@ -1697,17 +1695,10 @@ bool Monitor::Analyse() {
|
|||
} // end if zone is alarmed
|
||||
} // end foreach zone
|
||||
|
||||
if ( got_anal_image ) {
|
||||
if ( state == PREALARM )
|
||||
Event::AddPreAlarmFrame(snap_image, *timestamp, score, &alarm_image);
|
||||
Event::AddPreAlarmFrame(snap_image, *timestamp, score, (got_anal_image?&alarm_image:NULL));
|
||||
else
|
||||
event->AddFrame(snap_image, *timestamp, score, &alarm_image);
|
||||
} else {
|
||||
if ( state == PREALARM )
|
||||
Event::AddPreAlarmFrame(snap_image, *timestamp, score);
|
||||
else
|
||||
event->AddFrame(snap_image, *timestamp, score);
|
||||
}
|
||||
event->AddFrame(snap_image, *timestamp, score, (got_anal_image?&alarm_image:NULL));
|
||||
} else {
|
||||
// Not doing alarm frame storage
|
||||
if ( state == PREALARM ) {
|
||||
|
@ -1743,7 +1734,6 @@ bool Monitor::Analyse() {
|
|||
//set up video store data
|
||||
snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile());
|
||||
video_store_data->recording = event->StartTime();
|
||||
|
||||
}
|
||||
} // end if event
|
||||
|
||||
|
|
|
@ -220,7 +220,7 @@ protected:
|
|||
}
|
||||
|
||||
inline bool isConnected() const {
|
||||
return( connected );
|
||||
return connected && shared_data->valid;
|
||||
}
|
||||
inline time_t getLastConnectTime() const {
|
||||
return( last_connect_time );
|
||||
|
@ -463,7 +463,8 @@ public:
|
|||
|
||||
int GetOptSaveJPEGs() const { return savejpegs; }
|
||||
VideoWriter GetOptVideoWriter() const { return videowriter; }
|
||||
const std::vector<EncoderParameter_t>* GetOptEncoderParams() const { return &encoderparamsvec; }
|
||||
const std::vector<EncoderParameter_t>* GetOptEncoderParamsVec() const { return &encoderparamsvec; }
|
||||
const std::string GetOptEncoderParams() const { return encoderparams; }
|
||||
uint64_t GetVideoWriterEventId() const { return video_store_data->current_event; }
|
||||
void SetVideoWriterEventId( unsigned long long p_event_id ) { video_store_data->current_event = p_event_id; }
|
||||
struct timeval GetVideoWriterStartTime() const { return video_store_data->recording; }
|
||||
|
|
|
@ -329,8 +329,11 @@ bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) {
|
|||
gettimeofday(&frameStartTime, NULL);
|
||||
|
||||
fputs("--ZoneMinderFrame\r\nContent-Type: image/jpeg\r\n", stdout);
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
if (
|
||||
(0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size))
|
||||
||
|
||||
(fwrite(img_buffer, img_buffer_size, 1, stdout) != 1)
|
||||
) {
|
||||
if ( !zm_terminate )
|
||||
Warning("Unable to send stream frame: %s", strerror(errno));
|
||||
return false;
|
||||
|
@ -410,8 +413,11 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
|
|||
Error("Unexpected frame type %d", type);
|
||||
return false;
|
||||
}
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
if (
|
||||
(0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size))
|
||||
||
|
||||
(fwrite(img_buffer, img_buffer_size, 1, stdout) != 1)
|
||||
) {
|
||||
if ( !zm_terminate ) {
|
||||
// If the pipe was closed, we will get signalled SIGPIPE to exit, which will set zm_terminate
|
||||
Warning("Unable to send stream frame: %s", strerror(errno));
|
||||
|
|
|
@ -618,8 +618,8 @@ int RemoteCameraHttp::GetResponse() {
|
|||
static char *content_type_header;
|
||||
static char *boundary_header;
|
||||
static char *authenticate_header;
|
||||
static char subcontent_length_header[32];
|
||||
static char subcontent_type_header[64];
|
||||
static char subcontent_length_header[33];
|
||||
static char subcontent_type_header[65];
|
||||
|
||||
static char http_version[16];
|
||||
static char status_code[16];
|
||||
|
@ -901,12 +901,24 @@ int RemoteCameraHttp::GetResponse() {
|
|||
if ( !boundary_header && (strncasecmp(subheader_ptr, content_boundary, content_boundary_len) == 0) ) {
|
||||
boundary_header = subheader_ptr;
|
||||
Debug(4, "Got boundary subheader '%s'", subheader_ptr);
|
||||
} else if ( !subcontent_length_header[0] && (strncasecmp( subheader_ptr, content_length_match, content_length_match_len) == 0) ) {
|
||||
strncpy( subcontent_length_header, subheader_ptr+content_length_match_len, sizeof(subcontent_length_header) );
|
||||
} else if (
|
||||
!subcontent_length_header[0]
|
||||
&&
|
||||
(strncasecmp(subheader_ptr, content_length_match, content_length_match_len) == 0)
|
||||
) {
|
||||
strncpy(
|
||||
subcontent_length_header,
|
||||
subheader_ptr+content_length_match_len,
|
||||
sizeof(subcontent_length_header)-1
|
||||
);
|
||||
*(subcontent_length_header+strcspn(subcontent_length_header, "\r\n")) = '\0';
|
||||
Debug(4, "Got content length subheader '%s'", subcontent_length_header);
|
||||
} else if ( !subcontent_type_header[0] && (strncasecmp( subheader_ptr, content_type_match, content_type_match_len) == 0) ) {
|
||||
strncpy( subcontent_type_header, subheader_ptr+content_type_match_len, sizeof(subcontent_type_header) );
|
||||
strncpy(
|
||||
subcontent_type_header,
|
||||
subheader_ptr+content_type_match_len,
|
||||
sizeof(subcontent_type_header)-1
|
||||
);
|
||||
*(subcontent_type_header+strcspn(subcontent_type_header, "\r\n")) = '\0';
|
||||
Debug(4, "Got content type subheader '%s'", subcontent_type_header);
|
||||
} else {
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
unsigned int sseversion = 0;
|
||||
unsigned int sse_version = 0;
|
||||
unsigned int neonversion = 0;
|
||||
|
||||
std::string trimSet(std::string str, std::string trimset) {
|
||||
|
@ -45,10 +45,7 @@ std::string trimSet(std::string str, std::string trimset) {
|
|||
|
||||
// if all spaces or empty return an empty string
|
||||
if ( ( std::string::npos == startpos ) || ( std::string::npos == endpos ) )
|
||||
{
|
||||
return std::string("");
|
||||
}
|
||||
else
|
||||
return str.substr(startpos, endpos-startpos+1);
|
||||
}
|
||||
|
||||
|
@ -67,8 +64,7 @@ std::string replaceAll(std::string str, std::string from, std::string to) {
|
|||
return str;
|
||||
}
|
||||
|
||||
const std::string stringtf( const char *format, ... )
|
||||
{
|
||||
const std::string stringtf( const char *format, ... ) {
|
||||
va_list ap;
|
||||
char tempBuffer[8192];
|
||||
std::string tempString;
|
||||
|
@ -79,11 +75,10 @@ const std::string stringtf( const char *format, ... )
|
|||
|
||||
tempString = tempBuffer;
|
||||
|
||||
return( tempString );
|
||||
return tempString;
|
||||
}
|
||||
|
||||
const std::string stringtf( const std::string format, ... )
|
||||
{
|
||||
const std::string stringtf(const std::string format, ...) {
|
||||
va_list ap;
|
||||
char tempBuffer[8192];
|
||||
std::string tempString;
|
||||
|
@ -94,7 +89,7 @@ const std::string stringtf( const std::string format, ... )
|
|||
|
||||
tempString = tempBuffer;
|
||||
|
||||
return( tempString );
|
||||
return tempString;
|
||||
}
|
||||
|
||||
bool startsWith(const std::string &haystack, const std::string &needle) {
|
||||
|
@ -145,8 +140,7 @@ const std::string join(const StringVector &v, const char * delim=",") {
|
|||
const std::string base64Encode(const std::string &inString) {
|
||||
static char base64_table[64] = { '\0' };
|
||||
|
||||
if ( !base64_table[0] )
|
||||
{
|
||||
if ( !base64_table[0] ) {
|
||||
int i = 0;
|
||||
for ( char c = 'A'; c <= 'Z'; c++ )
|
||||
base64_table[i++] = c;
|
||||
|
@ -162,39 +156,32 @@ const std::string base64Encode(const std::string &inString) {
|
|||
outString.reserve(2 * inString.size());
|
||||
|
||||
const char *inPtr = inString.c_str();
|
||||
while( *inPtr )
|
||||
{
|
||||
while ( *inPtr ) {
|
||||
unsigned char selection = *inPtr >> 2;
|
||||
unsigned char remainder = (*inPtr++ & 0x03) << 4;
|
||||
outString += base64_table[selection];
|
||||
|
||||
if ( *inPtr )
|
||||
{
|
||||
if ( *inPtr ) {
|
||||
selection = remainder | (*inPtr >> 4);
|
||||
remainder = (*inPtr++ & 0x0f) << 2;
|
||||
outString += base64_table[selection];
|
||||
|
||||
if ( *inPtr )
|
||||
{
|
||||
if ( *inPtr ) {
|
||||
selection = remainder | (*inPtr >> 6);
|
||||
outString += base64_table[selection];
|
||||
selection = (*inPtr++ & 0x3f);
|
||||
outString += base64_table[selection];
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
outString += base64_table[remainder];
|
||||
outString += '=';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
outString += base64_table[remainder];
|
||||
outString += '=';
|
||||
outString += '=';
|
||||
}
|
||||
}
|
||||
return( outString );
|
||||
return outString;
|
||||
}
|
||||
|
||||
int split(const char* string, const char delim, std::vector<std::string>& items) {
|
||||
|
@ -240,7 +227,7 @@ int pairsplit(const char* string, const char delim, std::string& name, std::stri
|
|||
/* Detect special hardware features, such as SIMD instruction sets */
|
||||
void hwcaps_detect() {
|
||||
neonversion = 0;
|
||||
sseversion = 0;
|
||||
sse_version = 0;
|
||||
#if (defined(__i386__) || defined(__x86_64__))
|
||||
/* x86 or x86-64 processor */
|
||||
uint32_t r_edx, r_ecx, r_ebx;
|
||||
|
@ -278,31 +265,31 @@ void hwcaps_detect() {
|
|||
#endif
|
||||
|
||||
if ( r_ebx & 0x00000020 ) {
|
||||
sseversion = 52; /* AVX2 */
|
||||
sse_version = 52; /* AVX2 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with AVX2");
|
||||
} else if ( r_ecx & 0x10000000 ) {
|
||||
sseversion = 51; /* AVX */
|
||||
sse_version = 51; /* AVX */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with AVX");
|
||||
} else if ( r_ecx & 0x00100000 ) {
|
||||
sseversion = 42; /* SSE4.2 */
|
||||
sse_version = 42; /* SSE4.2 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE4.2");
|
||||
} else if ( r_ecx & 0x00080000 ) {
|
||||
sseversion = 41; /* SSE4.1 */
|
||||
sse_version = 41; /* SSE4.1 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE4.1");
|
||||
} else if ( r_ecx & 0x00000200 ) {
|
||||
sseversion = 35; /* SSSE3 */
|
||||
sse_version = 35; /* SSSE3 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSSE3");
|
||||
} else if ( r_ecx & 0x00000001 ) {
|
||||
sseversion = 30; /* SSE3 */
|
||||
sse_version = 30; /* SSE3 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE3");
|
||||
} else if ( r_edx & 0x04000000 ) {
|
||||
sseversion = 20; /* SSE2 */
|
||||
sse_version = 20; /* SSE2 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE2");
|
||||
} else if ( r_edx & 0x02000000 ) {
|
||||
sseversion = 10; /* SSE */
|
||||
sse_version = 10; /* SSE */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE");
|
||||
} else {
|
||||
sseversion = 0;
|
||||
sse_version = 0;
|
||||
Debug(1, "Detected a x86\\x86-64 processor");
|
||||
}
|
||||
#elif defined(__arm__)
|
||||
|
|
|
@ -59,7 +59,7 @@ 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 hwcaps_detect();
|
||||
extern unsigned int sseversion;
|
||||
extern unsigned int sse_version;
|
||||
extern unsigned int neonversion;
|
||||
|
||||
char *timeval_to_string( struct timeval tv );
|
||||
|
|
|
@ -37,11 +37,12 @@ VideoStore::VideoStore(
|
|||
const char *format_in,
|
||||
AVStream *p_video_in_stream,
|
||||
AVStream *p_audio_in_stream,
|
||||
Monitor *monitor
|
||||
Monitor *p_monitor
|
||||
) {
|
||||
|
||||
video_in_stream = p_video_in_stream;
|
||||
audio_in_stream = p_audio_in_stream;
|
||||
monitor = p_monitor;
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
//video_in_ctx = avcodec_alloc_context3(NULL);
|
||||
|
@ -213,11 +214,18 @@ VideoStore::VideoStore(
|
|||
}
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
|
||||
#if 0
|
||||
# This is commented out because we are only doing passthrough right now
|
||||
/* I'm not entirely sure that this is a good idea. We may have to do it someday but really only when transcoding
|
||||
* * think what I was trying to achieve here was to have zm_dump_codecpar output nice info
|
||||
* */
|
||||
#if 0
|
||||
|
||||
AVDictionary *opts = 0;
|
||||
ret = av_dict_parse_string(&opts, monitor->GetOptEncoderParams().c_str(), "=", ",", 0);
|
||||
if ( ret < 0 ) {
|
||||
Warning("Could not parse ffmpeg encoder options '%s'", monitor->GetOptEncoderParams().c_str());
|
||||
}
|
||||
|
||||
if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) {
|
||||
Warning("Can't open video codec (%s) %s",
|
||||
video_out_codec->name,
|
||||
|
@ -407,18 +415,36 @@ bool VideoStore::open() {
|
|||
if ( audio_out_stream ) zm_dump_stream_format(oc, 1, 0, 1);
|
||||
|
||||
AVDictionary *opts = NULL;
|
||||
|
||||
std::string option_string = monitor->GetOptEncoderParams();
|
||||
ret = av_dict_parse_string(&opts, option_string.c_str(), "=", ",\n", 0);
|
||||
if ( ret < 0 ) {
|
||||
Warning("Could not parse ffmpeg output options '%s'", option_string.c_str());
|
||||
}
|
||||
|
||||
const AVDictionaryEntry *movflags_entry = av_dict_get(opts, "movflags", NULL, AV_DICT_MATCH_CASE);
|
||||
if ( !movflags_entry ) {
|
||||
Debug(1, "setting movflags to frag_keyframe+empty_moov");
|
||||
// av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
|
||||
// Shiboleth reports that this may break seeking in mp4 before it downloads
|
||||
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
|
||||
// av_dict_set(&opts, "movflags",
|
||||
// "frag_keyframe+empty_moov+default_base_moof", 0);
|
||||
} else {
|
||||
Debug(1, "using movflags %s", movflags_entry->value);
|
||||
}
|
||||
if ( (ret = avformat_write_header(oc, &opts)) < 0 ) {
|
||||
// if ((ret = avformat_write_header(oc, &opts)) < 0) {
|
||||
Warning("Unable to set movflags to frag_custom+dash+delay_moov");
|
||||
/* Write the stream header, if any. */
|
||||
Warning("Unable to set movflags trying with defaults.");
|
||||
ret = avformat_write_header(oc, NULL);
|
||||
} else if ( av_dict_count(opts) != 0 ) {
|
||||
Warning("some options not set");
|
||||
Info("some options not used, turn on debugging for a list.");
|
||||
AVDictionaryEntry *e = NULL;
|
||||
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||
Debug(1, "Encoder Option %s=>%s", e->key, e->value);
|
||||
if ( !e->value ) {
|
||||
av_dict_set(&opts, e->key, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( opts ) av_dict_free(&opts);
|
||||
if ( ret < 0 ) {
|
||||
|
|
|
@ -19,7 +19,6 @@ extern "C" {
|
|||
|
||||
class VideoStore {
|
||||
private:
|
||||
|
||||
AVOutputFormat *out_format;
|
||||
AVFormatContext *oc;
|
||||
|
||||
|
@ -30,6 +29,7 @@ private:
|
|||
AVStream *video_in_stream;
|
||||
|
||||
AVStream *audio_in_stream;
|
||||
Monitor *monitor;
|
||||
|
||||
// Move this into the object so that we aren't constantly allocating/deallocating it on the stack
|
||||
AVPacket opkt;
|
||||
|
|
|
@ -227,7 +227,7 @@ bool Zone::CheckAlarms(const Image *delta_image) {
|
|||
|
||||
Debug(4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y);
|
||||
|
||||
/* if(config.cpu_extensions && sseversion >= 20) {
|
||||
/* if(config.cpu_extensions && sse_version >= 20) {
|
||||
sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
|
||||
} else {
|
||||
std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
|
||||
|
|
|
@ -259,6 +259,7 @@ int main(int argc, char *argv[]) {
|
|||
Debug(1, "Failed to prime capture of initial monitor");
|
||||
}
|
||||
prime_capture_log_count ++;
|
||||
if ( !zm_terminate )
|
||||
sleep(10);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ fi;
|
|||
|
||||
if [ "$DISTROS" == "" ]; then
|
||||
if [ "$RELEASE" != "" ]; then
|
||||
DISTROS="xenial,bionic,disco,eoan,focal,trusty"
|
||||
DISTROS="xenial,bionic,focal,trusty"
|
||||
else
|
||||
DISTROS=`lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`;
|
||||
fi;
|
||||
|
@ -220,15 +220,20 @@ IFS=',' ;for DISTRO in `echo "$DISTROS"`; do
|
|||
fi;
|
||||
|
||||
# Generate Changlog
|
||||
if [ "$DISTRO" == "trusty" ] || [ "$DISTRO" == "precise" ]; then
|
||||
if [ "$DISTRO" == "trusty" ] || [ "$DISTRO" == "precise" ]
|
||||
then
|
||||
cp -Rpd distros/ubuntu1204 debian
|
||||
else
|
||||
if [ "$DISTRO" == "wheezy" ]; then
|
||||
|
||||
elif [ "$DISTRO" == "wheezy" ]
|
||||
then
|
||||
cp -Rpd distros/debian debian
|
||||
|
||||
elif [ "$DISTRO" == "beowulf" ]
|
||||
then
|
||||
cp -Rpd distros/beowulf debian
|
||||
else
|
||||
cp -Rpd distros/ubuntu1604 debian
|
||||
fi;
|
||||
fi;
|
||||
|
||||
if [ "$DEBEMAIL" != "" ] && [ "$DEBFULLNAME" != "" ]; then
|
||||
AUTHOR="$DEBFULLNAME <$DEBEMAIL>"
|
||||
|
|
|
@ -37,7 +37,7 @@ echo "Target subfolder set to $targetfolder"
|
|||
echo
|
||||
|
||||
echo "Running \$(rsync -v -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1)"
|
||||
rsync -v --ignore-missing-args --exclude 'external-repo.noarch.rpm' -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1
|
||||
rsync -v --ignore-missing-args --exclude 'external-repo.noarch.rpm' -e 'ssh -v' build/*.{rpm,deb,dsc,tar.xz,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1
|
||||
if [ "$?" -eq 0 ]; then
|
||||
echo
|
||||
echo "Files copied successfully."
|
||||
|
|
|
@ -19,7 +19,7 @@ $statusData = array(
|
|||
'limit' => 1,
|
||||
'elements' => array(
|
||||
'MonitorCount' => array( 'sql' => 'count(*)' ),
|
||||
'ActiveMonitorCount' => array( 'sql' => 'count(if(Function != \'None\',1,NULL))' ),
|
||||
'ActiveMonitorCount' => array( 'sql' => 'count(if(`Function` != \'None\',1,NULL))' ),
|
||||
'State' => array( 'func' => 'daemonCheck()?'.translate('Running').':'.translate('Stopped') ),
|
||||
'Load' => array( 'func' => 'getLoad()' ),
|
||||
'Disk' => array( 'func' => 'getDiskPercent()' ),
|
||||
|
@ -246,7 +246,7 @@ function collectData() {
|
|||
if ( isset($elementData['sql']) )
|
||||
$fieldSql[] = $elementData['sql'].' as '.$element;
|
||||
else
|
||||
$fieldSql[] = $element;
|
||||
$fieldSql[] = '`'.$element.'`';
|
||||
if ( isset($elementData['table']) && isset($elementData['join']) ) {
|
||||
$joinSql[] = 'left join '.$elementData['table'].' on '.$elementData['join'];
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ function collectData() {
|
|||
|
||||
preg_match('/^(\w+)\s*(ASC|DESC)?( NULLS FIRST)?$/i', $sort_field, $matches);
|
||||
if ( count($matches) ) {
|
||||
if ( in_array($matches[1], $fieldSql) ) {
|
||||
if ( in_array($matches[1], $fieldSql) or in_array('`'.$matches[1].'`', $fieldSql) ) {
|
||||
$sql .= $matches[1];
|
||||
} else {
|
||||
ZM\Error('Sort field ' . $matches[1] . ' not in SQL Fields');
|
||||
|
@ -296,7 +296,7 @@ function collectData() {
|
|||
$sql .= ' '.strtoupper($matches[3]);
|
||||
}
|
||||
} else {
|
||||
ZM\Error("Sort field didn't match regexp $sort_field");
|
||||
ZM\Error('Sort field didn\'t match regexp '.$sort_field);
|
||||
}
|
||||
} # end foreach sort field
|
||||
} # end if has sort
|
||||
|
|
|
@ -128,27 +128,3 @@ global $configvals;
|
|||
foreach( $configvals as $key => $value) {
|
||||
Configure::write($key, $value);
|
||||
}
|
||||
if ( 0 ) {
|
||||
// No longer needed, but I want to keep the code for reference
|
||||
//
|
||||
// For Human-readability, use ZM_SERVER_HOST or ZM_SERVER_NAME in zm.conf, and convert it here to a ZM_SERVER_ID
|
||||
if ( ! defined('ZM_SERVER_ID') ) {
|
||||
App::uses('ClassRegistry', 'Utility');
|
||||
$ServerModel = ClassRegistry::init('Server');
|
||||
if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) {
|
||||
$Server = $ServerModel->find( 'first', array( 'conditions'=>array('Name'=>ZM_SERVER_NAME) ) );
|
||||
if ( ! $Server ) {
|
||||
Error('Invalid Multi-Server configration detected. ZM_SERVER_NAME set to ' . ZM_SERVER_NAME . ' in zm.conf, but no corresponding entry found in Servers table.');
|
||||
} else {
|
||||
define( 'ZM_SERVER_ID', $Server['Server']['Id'] );
|
||||
}
|
||||
} else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) {
|
||||
$Server = $ServerModel->find( 'first', array( 'conditions'=>array('Name'=>ZM_SERVER_HOST) ) );
|
||||
if ( ! $Server ) {
|
||||
Error('Invalid Multi-Server configration detected. ZM_SERVER_HOST set to ' . ZM_SERVER_HOST . ' in zm.conf, but no corresponding entry found in Servers table.');
|
||||
} else {
|
||||
define( 'ZM_SERVER_ID', $Server['Server']['Id'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -434,14 +434,11 @@ class EventsController extends AppController {
|
|||
// Find the max Frame for this Event. Error out otherwise.
|
||||
$this->loadModel('Frame');
|
||||
|
||||
if (! $frame = $this->Frame->find('first', array(
|
||||
$frame = $this->Frame->find('first', array(
|
||||
'conditions' => array(
|
||||
'EventId' => $event['Event']['Id'],
|
||||
'Score' => $event['Event']['MaxScore']
|
||||
)
|
||||
))) {
|
||||
throw new NotFoundException(__('Can not find Frame for Event ' . $event['Event']['Id']));
|
||||
}
|
||||
return $frame['Frame']['Id'];
|
||||
)));
|
||||
return empty($frame)?null:$frame['Frame']['Id'];
|
||||
}
|
||||
} // end class EventsController
|
||||
|
|
|
@ -14,6 +14,18 @@ class UsersController extends AppController {
|
|||
*/
|
||||
public $components = array('RequestHandler', 'Paginator');
|
||||
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
|
||||
global $user;
|
||||
# We already tested for auth in appController, so we just need to test for specific permission
|
||||
$canView = (!$user) || ($user['System'] != 'None');
|
||||
if ( !$canView ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* index method
|
||||
*
|
||||
|
@ -23,6 +35,12 @@ class UsersController extends AppController {
|
|||
public function index() {
|
||||
$this->User->recursive = 0;
|
||||
|
||||
global $user;
|
||||
# We should actually be able to list our own user, but I'm not bothering at this time.
|
||||
if ( $user['System'] == 'None' ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
$users = $this->Paginator->paginate('User');
|
||||
|
||||
$this->set(compact('users'));
|
||||
|
@ -36,16 +54,20 @@ class UsersController extends AppController {
|
|||
* @return void
|
||||
*/
|
||||
public function view($id = null) {
|
||||
$this->loadModel('Config');
|
||||
$configs = $this->Config->find('list', array(
|
||||
'fields' => array('Name', 'Value'),
|
||||
'conditions' => array('Name' => array('ZM_DIR_EVENTS'))
|
||||
));
|
||||
|
||||
$this->User->recursive = 1;
|
||||
|
||||
global $user;
|
||||
# We can view ourselves
|
||||
$canView = ($user['System'] != 'None') or ($user['Id'] == $id);
|
||||
if ( !$canView ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !$this->User->exists($id) ) {
|
||||
throw new NotFoundException(__('Invalid user'));
|
||||
}
|
||||
|
||||
$options = array('conditions' => array('User.' . $this->User->primaryKey => $id));
|
||||
$user = $this->User->find('first', $options);
|
||||
|
||||
|
@ -62,6 +84,13 @@ class UsersController extends AppController {
|
|||
*/
|
||||
public function add() {
|
||||
if ( $this->request->is('post') ) {
|
||||
|
||||
global $user;
|
||||
if ( $user['System'] != 'Edit' ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->User->create();
|
||||
if ( $this->User->save($this->request->data) ) {
|
||||
return $this->flash(__('The user has been saved.'), array('action' => 'index'));
|
||||
|
@ -82,6 +111,13 @@ class UsersController extends AppController {
|
|||
public function edit($id = null) {
|
||||
$this->User->id = $id;
|
||||
|
||||
global $user;
|
||||
$canEdit = ($user['System'] == 'Edit') or (($user['Id'] == $id) and ZM_USER_SELF_EDIT);
|
||||
if ( !$canEdit ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !$this->User->exists($id) ) {
|
||||
throw new NotFoundException(__('Invalid user'));
|
||||
}
|
||||
|
@ -93,8 +129,10 @@ class UsersController extends AppController {
|
|||
$message = 'Error';
|
||||
}
|
||||
} else {
|
||||
# What is this doing? Resetting the request data? I understand clearing the password field
|
||||
# but generally I feel like the request data should be read only
|
||||
$this->request->data = $this->User->read(null, $id);
|
||||
unset($this->request->data['User']['password']);
|
||||
unset($this->request->data['User']['Password']);
|
||||
}
|
||||
|
||||
$this->set(array(
|
||||
|
@ -112,6 +150,13 @@ class UsersController extends AppController {
|
|||
*/
|
||||
public function delete($id = null) {
|
||||
$this->User->id = $id;
|
||||
|
||||
global $user;
|
||||
# Can't delete ourselves
|
||||
if ( ($user['System'] != 'Edit') or ($user['Id'] == $id) ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
if ( !$this->User->exists() ) {
|
||||
throw new NotFoundException(__('Invalid user'));
|
||||
}
|
||||
|
@ -126,47 +171,4 @@ class UsersController extends AppController {
|
|||
'_serialize' => array('message')
|
||||
));
|
||||
}
|
||||
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
|
||||
$this->loadModel('Config');
|
||||
$configs = $this->Config->find('list', array(
|
||||
'fields' => array('Name', 'Value'),
|
||||
'conditions' => array('Name' => array('ZM_OPT_USE_AUTH'))
|
||||
));
|
||||
if ( $configs['ZM_OPT_USE_AUTH'] ) {
|
||||
$this->Auth->allow('add','logout');
|
||||
} else {
|
||||
$this->Auth->allow();
|
||||
}
|
||||
}
|
||||
|
||||
public function login() {
|
||||
$this->loadModel('Config');
|
||||
$configs = $this->Config->find('list', array(
|
||||
'fields' => array('Name', 'Value'),
|
||||
'conditions' => array('Name' => array('ZM_OPT_USE_AUTH'))
|
||||
));
|
||||
|
||||
if ( ! $configs['ZM_OPT_USE_AUTH'] ) {
|
||||
$this->set(array(
|
||||
'message' => 'Login is not required.',
|
||||
'_serialize' => array('message')
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
if ($this->Auth->login()) {
|
||||
return $this->redirect($this->Auth->redirectUrl());
|
||||
}
|
||||
$this->Session->setFlash(__('Invalid username or password, try again'));
|
||||
}
|
||||
}
|
||||
|
||||
public function logout() {
|
||||
return $this->redirect($this->Auth->logout());
|
||||
}
|
||||
|
||||
}
|
||||
} # end class UsersController
|
||||
|
|
|
@ -40,6 +40,7 @@ class ZonesController extends AppController {
|
|||
'_serialize' => array('zones')
|
||||
));
|
||||
}
|
||||
|
||||
public function index() {
|
||||
$this->Zone->recursive = -1;
|
||||
|
||||
|
@ -63,7 +64,11 @@ class ZonesController extends AppController {
|
|||
* @return void
|
||||
*/
|
||||
public function add() {
|
||||
if ( $this->request->is('post') ) {
|
||||
|
||||
if ( !$this->request->is('post') ) {
|
||||
throw new BadRequestException(__('Invalid method. Should be post'));
|
||||
return;
|
||||
}
|
||||
|
||||
global $user;
|
||||
$canEdit = (!$user) || $user['Monitors'] == 'Edit';
|
||||
|
@ -72,14 +77,30 @@ class ZonesController extends AppController {
|
|||
return;
|
||||
}
|
||||
|
||||
$zone = null;
|
||||
|
||||
$this->Zone->create();
|
||||
if ( $this->Zone->save($this->request->data) ) {
|
||||
return $this->flash(__('The zone has been saved.'), array('action' => 'index'));
|
||||
$zone = $this->Zone->save($this->request->data);
|
||||
if ( $zone ) {
|
||||
require_once __DIR__ .'/../../../includes/Monitor.php';
|
||||
$monitor = new ZM\Monitor($zone['Zone']['MonitorId']);
|
||||
$monitor->zmaControl('restart');
|
||||
$message = 'Saved';
|
||||
//$zone = $this->Zone->find('first', array('conditions' => array( array('Zone.' . $this->Zone->primaryKey => $this->Zone),
|
||||
} else {
|
||||
$message = 'Error: ';
|
||||
// if there is a validation message, use it
|
||||
if ( !$this->Zone->validates() ) {
|
||||
$message = $this->Zone->validationErrors;
|
||||
}
|
||||
}
|
||||
$monitors = $this->Zone->Monitor->find('list');
|
||||
$this->set(compact('monitors'));
|
||||
}
|
||||
|
||||
$this->set(array(
|
||||
'message' => $message,
|
||||
'zone' => $zone,
|
||||
'_serialize' => array('message','zone')
|
||||
));
|
||||
} // end function add()
|
||||
|
||||
/**
|
||||
* edit method
|
||||
|
|
|
@ -3,8 +3,6 @@ App::uses('AppModel', 'Model');
|
|||
/**
|
||||
* User Model
|
||||
*
|
||||
* @property Monitor $Monitor
|
||||
* @property Frame $Frame
|
||||
*/
|
||||
class User extends AppModel {
|
||||
|
||||
|
@ -23,6 +21,20 @@ class User extends AppModel {
|
|||
)
|
||||
);
|
||||
|
||||
function beforeFind($query) {
|
||||
if ( empty($query['fields']) ) {
|
||||
$schema = $this->schema();
|
||||
unset($schema['Password']);
|
||||
|
||||
foreach (array_keys($schema) as $field) {
|
||||
$query['fields'][] = $this->alias . '.' . $field;
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
return parent::beforeFind($query);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use table
|
||||
*
|
||||
|
@ -53,14 +65,6 @@ class User extends AppModel {
|
|||
* @var array
|
||||
*/
|
||||
public $belongsTo = array(
|
||||
/*'Monitor' => array(
|
||||
'className' => 'Monitor',
|
||||
'foreignKey' => 'MonitorId',
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => ''
|
||||
)
|
||||
*/
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -69,21 +73,6 @@ class User extends AppModel {
|
|||
* @var array
|
||||
*/
|
||||
public $hasMany = array(
|
||||
/*
|
||||
'Frame' => array(
|
||||
'className' => 'Frame',
|
||||
'foreignKey' => 'UserId',
|
||||
'dependent' => true,
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => '',
|
||||
'limit' => '',
|
||||
'offset' => '',
|
||||
'exclusive' => '',
|
||||
'finderQuery' => '',
|
||||
'counterQuery' => ''
|
||||
)
|
||||
*/
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,32 @@ class Zone extends AppModel {
|
|||
|
||||
public $recursive = -1;
|
||||
|
||||
/**
|
||||
* Validation rules
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $validate = array(
|
||||
'MonitorId' => array(
|
||||
'rule' => 'checkMonitorId',
|
||||
//array('naturalNumber'),
|
||||
'message' => 'Zones must have a valid MonitorId',
|
||||
'allowEmpty' => false,
|
||||
'required' => true,
|
||||
//'last' => false, // Stop validation after this rule
|
||||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
),
|
||||
'Name' => array(
|
||||
'required' => array(
|
||||
//'on' => 'create',
|
||||
'rule' => 'notBlank',
|
||||
'message' => 'Zone Name must be specified for creation',
|
||||
'required' => true,
|
||||
),
|
||||
)
|
||||
|
||||
);
|
||||
|
||||
//The Associations below have been created with all possible keys, those that are not needed can be removed
|
||||
|
||||
/**
|
||||
|
@ -41,9 +67,17 @@ class Zone extends AppModel {
|
|||
'Monitor' => array(
|
||||
'className' => 'Monitor',
|
||||
'foreignKey' => 'MonitorId',
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => ''
|
||||
//'conditions' => '',
|
||||
//'fields' => '',
|
||||
//'order' => ''
|
||||
)
|
||||
);
|
||||
|
||||
public function checkMonitorId($data) {
|
||||
if ( !$this->Monitor->find('first', array('conditions'=>array('Id'=>$data['MonitorId']))) ) {
|
||||
//$this->invalidate('MonitorId', 'Invalid Monitor Id');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
echo json_encode($message);
|
||||
echo json_encode($zone);
|
|
@ -0,0 +1,2 @@
|
|||
echo json_encode($message);
|
||||
echo json_encode($zone);
|
|
@ -0,0 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response'=>$message, 'zone'=>$zone));
|
||||
echo $xml->asXML();
|
|
@ -0,0 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response' => $message, 'zone'=>$zone));
|
||||
echo $xml->asXML();
|
|
@ -262,14 +262,19 @@ class Event extends ZM_Object {
|
|||
return $streamSrc;
|
||||
} // end function getStreamSrc
|
||||
|
||||
# The new='' is to so that if we pass null, we reset the value of DiskSpace.
|
||||
# '' is not a valid DiskSpace so that tells us that nothing was passed whereas null (unknown) is.
|
||||
function DiskSpace( $new='' ) {
|
||||
if ( is_null($new) or ( $new != '' ) ) {
|
||||
$this->{'DiskSpace'} = $new;
|
||||
}
|
||||
if ( (!property_exists($this, 'DiskSpace')) or (null === $this->{'DiskSpace'}) ) {
|
||||
$this->{'DiskSpace'} = folder_size($this->Path());
|
||||
if ( $this->{'EndTime'} ) {
|
||||
# Finished events shouldn't grow in size much so we can commit it to the db.
|
||||
dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'}));
|
||||
}
|
||||
}
|
||||
return $this->{'DiskSpace'};
|
||||
}
|
||||
|
||||
|
@ -389,7 +394,7 @@ class Event extends ZM_Object {
|
|||
if ( ( !$frame ) and file_exists($eventPath.'/snapshot.jpg') ) {
|
||||
# No frame specified, so look for a snapshot to use
|
||||
$captImage = 'snapshot.jpg';
|
||||
Logger::Debug("Frame not specified, using snapshot");
|
||||
Logger::Debug('Frame not specified, using snapshot');
|
||||
$frame = array('FrameId'=>'snapshot', 'Type'=>'', 'Delta'=>0);
|
||||
} else {
|
||||
$captImage = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyze.jpg', $frame['FrameId']);
|
||||
|
@ -401,19 +406,19 @@ class Event extends ZM_Object {
|
|||
$videoPath = $eventPath.'/'.$Event->DefaultVideo();
|
||||
|
||||
if ( !file_exists($videoPath) ) {
|
||||
Error("Event claims to have a video file, but it does not seem to exist at $videoPath" );
|
||||
Error('Event claims to have a video file, but it does not seem to exist at '.$videoPath);
|
||||
return '';
|
||||
}
|
||||
|
||||
#$command ='ffmpeg -v 0 -i '.$videoPath.' -vf "select=gte(n\\,'.$frame['FrameId'].'),setpts=PTS-STARTPTS" '.$eventPath.'/'.$captImage;
|
||||
$command ='ffmpeg -ss '. $frame['Delta'] .' -i '.$videoPath.' -frames:v 1 '.$eventPath.'/'.$captImage;
|
||||
Logger::Debug( "Running $command" );
|
||||
Logger::Debug('Running '.$command);
|
||||
$output = array();
|
||||
$retval = 0;
|
||||
exec($command, $output, $retval);
|
||||
Logger::Debug("Retval: $retval, output: " . implode("\n", $output));
|
||||
} else {
|
||||
Error("Can't create frame images from video because there is no video file for event ".$Event->Id().' at ' .$Event->Path() );
|
||||
Error('Can\'t create frame images from video because there is no video file for event '.$Event->Id().' at ' .$Event->Path());
|
||||
}
|
||||
} // end if capture file exists
|
||||
} // end if analyze file exists
|
||||
|
@ -421,7 +426,7 @@ class Event extends ZM_Object {
|
|||
|
||||
$captPath = $eventPath.'/'.$captImage;
|
||||
if ( !file_exists($captPath) ) {
|
||||
Error("Capture file does not exist at $captPath");
|
||||
Error('Capture file does not exist at '.$captPath);
|
||||
}
|
||||
|
||||
$analImage = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyse.jpg', $frame['FrameId']);
|
||||
|
@ -484,7 +489,7 @@ class Event extends ZM_Object {
|
|||
);
|
||||
|
||||
return $imageData;
|
||||
}
|
||||
} # getImageSrc
|
||||
|
||||
public function link_to($text=null) {
|
||||
if ( !$text )
|
||||
|
|
|
@ -19,9 +19,9 @@ class Group extends ZM_Object {
|
|||
|
||||
public function delete() {
|
||||
if ( property_exists($this, 'Id') ) {
|
||||
dbQuery('DELETE FROM Groups_Monitors WHERE GroupId=?', array($this->{'Id'}));
|
||||
dbQuery('UPDATE Groups SET ParentId=NULL WHERE ParentId=?', array($this->{'Id'}));
|
||||
dbQuery('DELETE FROM Groups WHERE Id=?', array($this->{'Id'}));
|
||||
dbQuery('DELETE FROM `Groups_Monitors` WHERE `GroupId`=?', array($this->{'Id'}));
|
||||
dbQuery('UPDATE `Groups` SET `ParentId`=NULL WHERE `ParentId`=?', array($this->{'Id'}));
|
||||
dbQuery('DELETE FROM `Groups` WHERE Id=?', array($this->{'Id'}));
|
||||
if ( isset($_COOKIE['zmGroup']) ) {
|
||||
if ( $this->{'Id'} == $_COOKIE['zmGroup'] ) {
|
||||
unset($_COOKIE['zmGroup']);
|
||||
|
@ -47,7 +47,7 @@ class Group extends ZM_Object {
|
|||
|
||||
public function MonitorIds( ) {
|
||||
if ( ! property_exists($this, 'MonitorIds') ) {
|
||||
$this->{'MonitorIds'} = dbFetchAll('SELECT MonitorId FROM Groups_Monitors WHERE GroupId=?', 'MonitorId', array($this->{'Id'}));
|
||||
$this->{'MonitorIds'} = dbFetchAll('SELECT `MonitorId` FROM `Groups_Monitors` WHERE `GroupId`=?', 'MonitorId', array($this->{'Id'}));
|
||||
}
|
||||
return $this->{'MonitorIds'};
|
||||
}
|
||||
|
|
|
@ -201,6 +201,11 @@ class Monitor extends ZM_Object {
|
|||
if ( ZM_RAND_STREAM ) {
|
||||
$args['rand'] = time();
|
||||
}
|
||||
foreach ( array('scale') as $int_arg ) {
|
||||
if ( isset($args[$int_arg]) and (!is_numeric($args[$int_arg]) or !$args[$int_arg] ) ) {
|
||||
unset($args[$int_arg]);
|
||||
}
|
||||
}
|
||||
|
||||
$streamSrc .= '?'.http_build_query($args, '', $querySep);
|
||||
|
||||
|
@ -293,7 +298,7 @@ class Monitor extends ZM_Object {
|
|||
return;
|
||||
}
|
||||
}
|
||||
Logger::Debug("sending command to $url");
|
||||
Logger::Debug('sending command to '.$url);
|
||||
|
||||
$context = stream_context_create();
|
||||
try {
|
||||
|
@ -317,7 +322,8 @@ class Monitor extends ZM_Object {
|
|||
|
||||
if ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
|
||||
if ( $this->{'Function'} == 'None' || $this->{'Function'} == 'Monitor' || $mode == 'stop' ) {
|
||||
if ( ZM_OPT_CONTROL ) {
|
||||
if ( ZM_OPT_CONTROL && $this->Controllable() && $this->TrackMotion() &&
|
||||
( $this->{'Function'} == 'Modect' || $this->{'Function'} == 'Mocord' ) ) {
|
||||
daemonControl('stop', 'zmtrack.pl', '-m '.$this->{'Id'});
|
||||
}
|
||||
daemonControl('stop', 'zma', '-m '.$this->{'Id'});
|
||||
|
@ -340,7 +346,7 @@ class Monitor extends ZM_Object {
|
|||
} else if ( $this->ServerId() ) {
|
||||
$Server = $this->Server();
|
||||
|
||||
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zma.json';
|
||||
$url = $Server->UrlToApi().'/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zma.json';
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
|
@ -490,12 +496,11 @@ class Monitor extends ZM_Object {
|
|||
foreach ( explode(' ', $command) as $option ) {
|
||||
if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
|
||||
$options[$matches[1]] = $matches[2]?$matches[2]:1;
|
||||
} else if ( $option != '' and $option != 'quit' ) {
|
||||
} else if ( $option != '' and $option != 'quit' and $option != 'start' and $option != 'stop' ) {
|
||||
Warning("Ignored command for zmcontrol $option in $command");
|
||||
}
|
||||
}
|
||||
if ( !count($options) ) {
|
||||
|
||||
if ( $command == 'quit' or $command == 'start' or $command == 'stop' ) {
|
||||
# These are special as we now run zmcontrol as a daemon through zmdc.
|
||||
$status = daemonStatus('zmcontrol.pl', array('--id', $this->{'Id'}));
|
||||
|
@ -539,7 +544,7 @@ class Monitor extends ZM_Object {
|
|||
} else if ( $this->ServerId() ) {
|
||||
$Server = $this->Server();
|
||||
|
||||
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json';
|
||||
$url = $Server->UrlToApi().'/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json';
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
|
|
|
@ -306,7 +306,7 @@ class ZM_Object {
|
|||
$fields = array_keys($fields);
|
||||
|
||||
if ( $this->Id() ) {
|
||||
$sql = 'UPDATE '.$table.' SET '.implode(', ', array_map(function($field) {return '`'.$field.'`=?';}, $fields)).' WHERE Id=?';
|
||||
$sql = 'UPDATE `'.$table.'` SET '.implode(', ', array_map(function($field) {return '`'.$field.'`=?';}, $fields)).' WHERE Id=?';
|
||||
$values = array_map(function($field){ return $this->{$field};}, $fields);
|
||||
$values[] = $this->{'Id'};
|
||||
if ( dbQuery($sql, $values) )
|
||||
|
@ -314,8 +314,8 @@ class ZM_Object {
|
|||
} else {
|
||||
unset($fields['Id']);
|
||||
|
||||
$sql = 'INSERT INTO '.$table.
|
||||
' ('.implode(', ', array_map(function($field) {return '`'.$field.'`';}, $fields)).
|
||||
$sql = 'INSERT INTO `'.$table.
|
||||
'` ('.implode(', ', array_map(function($field) {return '`'.$field.'`';}, $fields)).
|
||||
') VALUES ('.
|
||||
implode(', ', array_map(function($field){return '?';}, $fields)).')';
|
||||
|
||||
|
@ -331,7 +331,7 @@ class ZM_Object {
|
|||
public function delete() {
|
||||
$class = get_class($this);
|
||||
$table = $class::$table;
|
||||
dbQuery("DELETE FROM $table WHERE Id=?", array($this->{'Id'}));
|
||||
dbQuery("DELETE FROM `$table` WHERE Id=?", array($this->{'Id'}));
|
||||
if ( isset($object_cache[$class]) and isset($object_cache[$class][$this->{'Id'}]) )
|
||||
unset($object_cache[$class][$this->{'Id'}]);
|
||||
}
|
||||
|
|
|
@ -85,8 +85,6 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
|
|||
// We update the request id so that the newly saved filter is auto-selected
|
||||
$_REQUEST['Id'] = $filter->Id();
|
||||
}
|
||||
if ( $filter->Background() )
|
||||
$filter->control('start');
|
||||
|
||||
if ( $action == 'execute' ) {
|
||||
$filter->execute();
|
||||
|
@ -94,6 +92,8 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
|
|||
$filter->delete();
|
||||
|
||||
$view = 'events';
|
||||
} else if ( $filter->Background() ) {
|
||||
$filter->control('start');
|
||||
}
|
||||
|
||||
} else if ( $action == 'control' ) {
|
||||
|
|
|
@ -18,16 +18,24 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( $action == 'user' ) {
|
||||
if ( $action == 'Save' ) {
|
||||
if ( canEdit('System') ) {
|
||||
if ( !empty($_REQUEST['uid']) )
|
||||
if ( !empty($_REQUEST['uid']) ) {
|
||||
$dbUser = dbFetchOne('SELECT * FROM Users WHERE Id=?', NULL, array($_REQUEST['uid']));
|
||||
else
|
||||
} else {
|
||||
$dbUser = array();
|
||||
}
|
||||
|
||||
$types = array();
|
||||
if ( isset($_REQUEST['newUser']['MonitorIds']) and is_array($_REQUEST['newUser']['MonitorIds']) )
|
||||
$_REQUEST['newUser']['MonitorIds'] = implode(',', $_REQUEST['newUser']['MonitorIds']);
|
||||
if ( !$_REQUEST['newUser']['Password'] )
|
||||
unset($_REQUEST['newUser']['Password']);
|
||||
|
||||
$changes = getFormChanges($dbUser, $_REQUEST['newUser'], $types);
|
||||
|
||||
|
||||
if ( isset($_REQUEST['newUser']['Password']) ) {
|
||||
if ( function_exists('password_hash') ) {
|
||||
$pass_hash = '"'.password_hash($_REQUEST['newUser']['Password'], PASSWORD_BCRYPT).'"';
|
||||
} else {
|
||||
|
@ -40,6 +48,7 @@ if ( $action == 'user' ) {
|
|||
} else {
|
||||
unset($changes['Password']);
|
||||
}
|
||||
}
|
||||
|
||||
if ( count($changes) ) {
|
||||
if ( !empty($_REQUEST['uid']) ) {
|
||||
|
|
|
@ -260,6 +260,22 @@ function userFromSession() {
|
|||
return $user;
|
||||
}
|
||||
|
||||
function get_auth_relay() {
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
return 'auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
} else if ( ZM_AUTH_RELAY == 'plain' ) {
|
||||
// password probably needs to be escaped
|
||||
return 'username='.$_SESSION['username'].'&password='.urlencode($_SESSION['password']);
|
||||
} else if ( ZM_AUTH_RELAY == 'none' ) {
|
||||
return 'username='.$_SESSION['username'];
|
||||
} else {
|
||||
ZM\Error('Unknown value for ZM_AUTH_RELAY ' . ZM_AUTH_RELAY);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
} // end function get_auth_relay
|
||||
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( !empty($_REQUEST['token']) ) {
|
||||
// we only need to get the username here
|
||||
|
|
|
@ -389,7 +389,7 @@ function csrf_conf($key, $val) {
|
|||
*/
|
||||
function csrf_start() {
|
||||
if ($GLOBALS['csrf']['auto-session'] && !session_id()) {
|
||||
session_start();
|
||||
zm_session_start();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,20 +25,26 @@ define('DB_LOG_DEBUG', 2);
|
|||
$GLOBALS['dbLogLevel'] = DB_LOG_OFF;
|
||||
|
||||
$GLOBALS['dbConn'] = false;
|
||||
require_once('logger.php');
|
||||
|
||||
function dbConnect() {
|
||||
global $dbConn;
|
||||
|
||||
$socket = '';
|
||||
if ( ZM_DB_HOST ) {
|
||||
if ( strpos(ZM_DB_HOST, ':') ) {
|
||||
// Host variable may carry a port or socket.
|
||||
list($host, $portOrSocket) = explode(':', ZM_DB_HOST, 2);
|
||||
if ( ctype_digit($portOrSocket) ) {
|
||||
$socket = ':host='.$host . ';port='.$portOrSocket;
|
||||
$socket = ':host='.$host . ';port='.$portOrSocket.';';
|
||||
} else {
|
||||
$socket = ':unix_socket='.$portOrSocket;
|
||||
$socket = ':unix_socket='.$portOrSocket.';';
|
||||
}
|
||||
} else {
|
||||
$socket = ':host='.ZM_DB_HOST;
|
||||
$socket = ':host='.ZM_DB_HOST.';';
|
||||
}
|
||||
} else {
|
||||
$socket = ':host=localhost;';
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -49,9 +55,9 @@ function dbConnect() {
|
|||
PDO::MYSQL_ATTR_SSL_KEY => ZM_DB_SSL_CLIENT_KEY,
|
||||
PDO::MYSQL_ATTR_SSL_CERT => ZM_DB_SSL_CLIENT_CERT,
|
||||
);
|
||||
$dbConn = new PDO(ZM_DB_TYPE . $socket . ';dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS, $dbOptions);
|
||||
$dbConn = new PDO(ZM_DB_TYPE.$socket.'dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS, $dbOptions);
|
||||
} else {
|
||||
$dbConn = new PDO(ZM_DB_TYPE . $socket . ';dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS);
|
||||
$dbConn = new PDO(ZM_DB_TYPE.$socket.'dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS);
|
||||
}
|
||||
|
||||
$dbConn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
|
@ -61,9 +67,12 @@ function dbConnect() {
|
|||
error_log('Unable to connect to ZM DB ' . $ex->getMessage());
|
||||
$dbConn = null;
|
||||
}
|
||||
}
|
||||
return $dbConn;
|
||||
} // end function dbConnect
|
||||
|
||||
dbConnect();
|
||||
if ( !dbConnect() ) {
|
||||
ZM\Fatal("Failed db connection to $socket");
|
||||
}
|
||||
|
||||
function dbDisconnect() {
|
||||
global $dbConn;
|
||||
|
|
|
@ -40,7 +40,7 @@ function CSPHeaders($view, $nonce) {
|
|||
if ( ! $Servers )
|
||||
$Servers = ZM\Server::find();
|
||||
|
||||
$additionalScriptSrc = implode(' ', array_map(function($S){return $S->Url();}, $Servers));
|
||||
$additionalScriptSrc = implode(' ', array_map(function($S){return $S->Hostname();}, $Servers));
|
||||
switch ($view) {
|
||||
case 'login': {
|
||||
if (defined('ZM_OPT_USE_GOOG_RECAPTCHA')
|
||||
|
@ -840,8 +840,14 @@ function daemonStatus($daemon, $args=false) {
|
|||
initDaemonStatus();
|
||||
|
||||
$string = $daemon;
|
||||
if ( $args )
|
||||
if ( $args ) {
|
||||
if ( is_array($args) ) {
|
||||
$string .= join(' ', $args);
|
||||
ZM\Warning("daemonStatus args: $string");
|
||||
} else {
|
||||
$string .= ' ' . $args;
|
||||
}
|
||||
}
|
||||
return ( strpos($daemon_status, "'$string' running") !== false );
|
||||
}
|
||||
|
||||
|
@ -1484,15 +1490,15 @@ function getLoad() {
|
|||
function getDiskPercent($path = ZM_DIR_EVENTS) {
|
||||
$total = disk_total_space($path);
|
||||
if ( $total === false ) {
|
||||
Error('disk_total_space returned false. Verify the web account user has access to ' . $path);
|
||||
ZM\Error('disk_total_space returned false. Verify the web account user has access to ' . $path);
|
||||
return 0;
|
||||
} elseif ( $total == 0 ) {
|
||||
Error('disk_total_space indicates the following path has a filesystem size of zero bytes ' . $path);
|
||||
ZM\Error('disk_total_space indicates the following path has a filesystem size of zero bytes ' . $path);
|
||||
return 100;
|
||||
}
|
||||
$free = disk_free_space($path);
|
||||
if ( $free === false ) {
|
||||
Error('disk_free_space returned false. Verify the web account user has access to ' . $path);
|
||||
ZM\Error('disk_free_space returned false. Verify the web account user has access to ' . $path);
|
||||
}
|
||||
$space = round((($total - $free) / $total) * 100);
|
||||
return $space;
|
||||
|
@ -2048,7 +2054,7 @@ function logState() {
|
|||
if ( $count['Level'] <= ZM\Logger::PANIC )
|
||||
$count['Level'] = ZM\Logger::FATAL;
|
||||
if ( !($levelCount = $levelCounts[$count['Level']]) ) {
|
||||
Error('Unexpected Log level '.$count['Level']);
|
||||
ZM\Error('Unexpected Log level '.$count['Level']);
|
||||
next;
|
||||
}
|
||||
if ( $levelCount[1] && $count['LevelCount'] >= $levelCount[1] ) {
|
||||
|
@ -2078,15 +2084,20 @@ function checkJsonError($value) {
|
|||
$value = var_export($value, true);
|
||||
switch ( json_last_error() ) {
|
||||
case JSON_ERROR_DEPTH :
|
||||
ZM\Fatal("Unable to decode JSON string '$value', maximum stack depth exceeded");
|
||||
ZM\Error("Unable to decode JSON string '$value', maximum stack depth exceeded");
|
||||
break;
|
||||
case JSON_ERROR_CTRL_CHAR :
|
||||
ZM\Fatal("Unable to decode JSON string '$value', unexpected control character found");
|
||||
ZM\Error("Unable to decode JSON string '$value', unexpected control character found");
|
||||
break;
|
||||
case JSON_ERROR_STATE_MISMATCH :
|
||||
ZM\Fatal("Unable to decode JSON string '$value', invalid or malformed JSON");
|
||||
ZM\Error("Unable to decode JSON string '$value', invalid or malformed JSON");
|
||||
break;
|
||||
case JSON_ERROR_SYNTAX :
|
||||
ZM\Fatal("Unable to decode JSON string '$value', syntax error");
|
||||
ZM\Error("Unable to decode JSON string '$value', syntax error");
|
||||
break;
|
||||
default :
|
||||
ZM\Fatal("Unable to decode JSON string '$value', unexpected error ".json_last_error());
|
||||
ZM\Error("Unable to decode JSON string '$value', unexpected error ".json_last_error());
|
||||
break;
|
||||
case JSON_ERROR_NONE:
|
||||
break;
|
||||
}
|
||||
|
@ -2290,7 +2301,8 @@ function validHtmlStr($input) {
|
|||
function getStreamHTML($monitor, $options = array()) {
|
||||
|
||||
if ( isset($options['scale']) ) {
|
||||
if ( $options['scale'] != 'auto' && $options['scale'] != '0' ) {
|
||||
if ( $options['scale'] != 'auto' && $options['scale'] != '0' and $options['scale'] != '' ) {
|
||||
ZM\Logger::Debug("Setting dimensions from scale:".$options['scale']);
|
||||
$options['width'] = reScale($monitor->ViewWidth(), $options['scale']).'px';
|
||||
$options['height'] = reScale($monitor->ViewHeight(), $options['scale']).'px';
|
||||
} else {
|
||||
|
|
|
@ -87,6 +87,7 @@ $SLANG = array(
|
|||
'Actual' => 'Actual',
|
||||
'AddNewControl' => 'Add New Control',
|
||||
'AddNewMonitor' => 'Add',
|
||||
'AddMonitorDisabled' => 'Your user is not allowed to add a new monitor',
|
||||
'AddNewServer' => 'Add New Server',
|
||||
'AddNewStorage' => 'Add New Storage',
|
||||
'AddNewUser' => 'Add New User',
|
||||
|
@ -983,6 +984,18 @@ $OLANG = array(
|
|||
"loglevel=debug" Set verbosity of FFmpeg (quiet, panic, fatal, error, warning, info, verbose, debug)
|
||||
'
|
||||
),
|
||||
'OPTIONS_ENCODER_PARAMETERS' => array(
|
||||
'Help' => '
|
||||
Parameters passed to the encoding codec. name=value separated by either , or newline.~~
|
||||
For example to changing quality, use the crf option. 1 is best, 51 is worst 23 is default.~~
|
||||
~~
|
||||
crf=23~~
|
||||
~~
|
||||
You might want to alter the movflags value to support different behaviours. Some people have troubles viewing videos due to the frag_keyframe option, but that option is supposed to allow viewing of incomplete events. See
|
||||
[https://ffmpeg.org/ffmpeg-formats.html](https://ffmpeg.org/ffmpeg-formats.html)
|
||||
for more information. ZoneMinder\'s default is frag_keyframe,empty_moov~~
|
||||
',
|
||||
),
|
||||
'OPTIONS_DECODERHWACCELNAME' => array(
|
||||
'Help' => '
|
||||
This is equivalent to the ffmpeg -hwaccel command line option. With intel graphics support, use "vaapi". For NVIDIA cuda support use "cuda". To check for support, run ffmpeg -hwaccels on the command line.'
|
||||
|
|
|
@ -509,7 +509,7 @@ th.table-th-sort-rev span.table-th-sort-span {
|
|||
}
|
||||
|
||||
#content {
|
||||
width: 96%;
|
||||
width: 100%;
|
||||
margin: 0 auto 8px auto;
|
||||
line-height: 130%;
|
||||
text-align: center;
|
||||
|
|
|
@ -11,10 +11,30 @@
|
|||
|
||||
textarea,
|
||||
input[name="newMonitor[Name]"],
|
||||
input[name="newMonitor[LabelFormat]"],
|
||||
input[name="newMonitor[ControlDevice]"],
|
||||
input[name="newMonitor[ControlAddress]"] {
|
||||
width: 100%;
|
||||
}
|
||||
input[name="newMonitor[AnalysisFPSLimit]"],
|
||||
input[name="newMonitor[MaxFPS]"],
|
||||
input[name="newMonitor[AlarmMaxFPS]"],
|
||||
input[name="newMonitor[V4LCapturesPerFrame]"]{
|
||||
width: 60px;
|
||||
}
|
||||
input[name="newMonitor[Port]"],
|
||||
input[name="newMonitor[Refresh]"],
|
||||
input[name="newMonitor[LabelX]"],
|
||||
input[name="newMonitor[LabelY]"],
|
||||
input[name="newMonitor[ImageBufferCount]"],
|
||||
input[name="newMonitor[WarmupCount]"],
|
||||
input[name="newMonitor[PreEventCount]"],
|
||||
input[name="newMonitor[PostEventCount]"],
|
||||
input[name="newMonitor[StreamReplayBuffer]"],
|
||||
input[name="newMonitor[AlarmFrameCount]"],
|
||||
input[name="newMonitor[AutoStopTimeout]"],
|
||||
input[name="newMonitor[TrackDelay]"],
|
||||
input[name="newMonitor[ReturnDelay]"],
|
||||
input[name="newMonitor[Width]"],
|
||||
input[name="newMonitor[Height]"] {
|
||||
width: 80px;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue