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
|
# Configuration for probot-stale - https://github.com/probot/stale
|
||||||
|
|
||||||
# Number of days of inactivity before an issue becomes 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
|
# Number of days of inactivity before a stale issue is closed
|
||||||
daysUntilClose: 7
|
daysUntilClose: 30
|
||||||
|
|
||||||
# Issues with these labels will never be considered stale
|
# Issues with these labels will never be considered stale
|
||||||
exemptLabels:
|
exemptLabels:
|
||||||
|
|
|
@ -875,7 +875,6 @@ configure_file(zmlinkcontent.sh.in "${CMAKE_CURRENT_BINARY_DIR}/zmlinkcontent.sh
|
||||||
|
|
||||||
# Create a target for man pages
|
# Create a target for man pages
|
||||||
include(Pod2Man)
|
include(Pod2Man)
|
||||||
ADD_MANPAGE_TARGET()
|
|
||||||
|
|
||||||
# Process subdirectories
|
# Process subdirectories
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,7 @@ MACRO(POD2MAN PODFILE MANFILE SECTION MANPAGE_DEST_PREFIX)
|
||||||
|
|
||||||
SET(MANPAGE_TARGET "man-${MANFILE}")
|
SET(MANPAGE_TARGET "man-${MANFILE}")
|
||||||
|
|
||||||
ADD_CUSTOM_TARGET(${MANPAGE_TARGET} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz)
|
ADD_CUSTOM_TARGET(${MANPAGE_TARGET} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz)
|
||||||
ADD_DEPENDENCIES(man ${MANPAGE_TARGET})
|
|
||||||
|
|
||||||
INSTALL(
|
INSTALL(
|
||||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz
|
FILES ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz
|
||||||
|
|
|
@ -46,3 +46,6 @@ ZM_PATH_SWAP=@ZM_TMPDIR@
|
||||||
# Full path to optional arp binary
|
# Full path to optional arp binary
|
||||||
# ZoneMinder will find the arp binary automatically on most systems
|
# ZoneMinder will find the arp binary automatically on most systems
|
||||||
ZM_PATH_ARP="@ZM_PATH_ARP@"
|
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',
|
`Hue` mediumint(7) NOT NULL default '-1',
|
||||||
`Colour` mediumint(7) NOT NULL default '-1',
|
`Colour` mediumint(7) NOT NULL default '-1',
|
||||||
`EventPrefix` varchar(32) NOT NULL default 'Event-',
|
`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',
|
`LabelX` smallint(5) unsigned NOT NULL default '0',
|
||||||
`LabelY` smallint(5) unsigned NOT NULL default '0',
|
`LabelY` smallint(5) unsigned NOT NULL default '0',
|
||||||
`LabelSize` smallint(5) unsigned NOT NULL DEFAULT '1',
|
`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
|
%global _hardened_build 1
|
||||||
|
|
||||||
Name: zoneminder
|
Name: zoneminder
|
||||||
Version: 1.34.14
|
Version: 1.34.20
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: A camera monitoring and analysis tool
|
Summary: A camera monitoring and analysis tool
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
|
|
|
@ -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)
|
#configure_file(zmeventdump.in zmeventdump @ONLY)
|
||||||
|
|
||||||
# Generate man files for the perl scripts destined for the bin folder
|
# 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})
|
FOREACH(PERLSCRIPT ${perlscripts})
|
||||||
get_filename_component(PERLSCRIPTNAME ${PERLSCRIPT} NAME)
|
get_filename_component(PERLSCRIPTNAME ${PERLSCRIPT} NAME)
|
||||||
POD2MAN(${PERLSCRIPT} zoneminder-${PERLSCRIPTNAME} 8 ${ZM_MANPAGE_DEST_PREFIX})
|
POD2MAN(${PERLSCRIPT} zoneminder-${PERLSCRIPTNAME} 8 ${ZM_MANPAGE_DEST_PREFIX})
|
||||||
|
|
|
@ -69,7 +69,7 @@ sub sendCmd {
|
||||||
|
|
||||||
my $result = undef;
|
my $result = undef;
|
||||||
|
|
||||||
printMsg($cmd, 'Tx');
|
$self->printMsg($cmd, 'Tx');
|
||||||
|
|
||||||
my $req = HTTP::Request->new(POST=>"http://$self->{Monitor}->{ControlAddress}/$cgi.cgi");
|
my $req = HTTP::Request->new(POST=>"http://$self->{Monitor}->{ControlAddress}/$cgi.cgi");
|
||||||
$req->content($cmd);
|
$req->content($cmd);
|
||||||
|
|
|
@ -143,10 +143,10 @@ sub PutCmd {
|
||||||
} else {
|
} else {
|
||||||
Info('Missing username and password in Control Address.');
|
Info('Missing username and password in Control Address.');
|
||||||
}
|
}
|
||||||
Fatal($res->status_line);
|
Error($res->status_line);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Fatal($res->status_line);
|
Error($res->status_line);
|
||||||
}
|
}
|
||||||
} # end unless res->is_success
|
} # end unless res->is_success
|
||||||
} # end sub putCmd
|
} # end sub putCmd
|
||||||
|
|
|
@ -49,9 +49,9 @@ my %options;
|
||||||
GetOptions(
|
GetOptions(
|
||||||
'id=i' =>\$id,
|
'id=i' =>\$id,
|
||||||
'command=s' =>\$options{command},
|
'command=s' =>\$options{command},
|
||||||
'xcoord=i' =>\$options{xcoord},
|
'xcoord=f' =>\$options{xcoord},
|
||||||
'ycoord=i' =>\$options{ycoord},
|
'ycoord=f' =>\$options{ycoord},
|
||||||
'speed=i' =>\$options{speed},
|
'speed=f' =>\$options{speed},
|
||||||
'step=i' =>\$options{step},
|
'step=i' =>\$options{step},
|
||||||
'panspeed=i' =>\$options{panspeed},
|
'panspeed=i' =>\$options{panspeed},
|
||||||
'tiltspeed=i' =>\$options{tiltspeed},
|
'tiltspeed=i' =>\$options{tiltspeed},
|
||||||
|
|
|
@ -160,7 +160,7 @@ if ( !$server_up ) {
|
||||||
use ZoneMinder::Server qw(CpuLoad);
|
use ZoneMinder::Server qw(CpuLoad);
|
||||||
if ( ! defined $dbh->do(q{UPDATE Servers SET Status=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?}, undef,
|
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} ) ) {
|
'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
|
# Server is not up. Some commands can still be handled
|
||||||
|
@ -191,8 +191,8 @@ if ( !$server_up ) {
|
||||||
my $attempts = 0;
|
my $attempts = 0;
|
||||||
while ( !connect(CLIENT, $saddr) ) {
|
while ( !connect(CLIENT, $saddr) ) {
|
||||||
$attempts++;
|
$attempts++;
|
||||||
Debug('Waiting for zmdc.pl server process at '.SOCK_FILE.", attempt $attempts");
|
Debug('Waiting for zmdc.pl server process at '.SOCK_FILE.', attempt '.$attempts);
|
||||||
Fatal("Can't connect: $!") if $attempts > MAX_CONNECT_DELAY;
|
Fatal('Can\'t connect to zmdc.pl server process at '.SOCK_FILE.': '.$!) if $attempts > MAX_CONNECT_DELAY;
|
||||||
usleep(200000);
|
usleep(200000);
|
||||||
} # end while
|
} # end while
|
||||||
} elsif ( defined($cpid) ) {
|
} elsif ( defined($cpid) ) {
|
||||||
|
@ -255,7 +255,7 @@ sub run {
|
||||||
close($PID);
|
close($PID);
|
||||||
} else {
|
} else {
|
||||||
# Log not initialized at this point so use die instead
|
# 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;
|
my $fd = 0;
|
||||||
|
@ -308,6 +308,7 @@ sub run {
|
||||||
while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) {
|
while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) {
|
||||||
Warning("Not connected to db ($dbh)".($dbh?' ping('.$dbh->ping().')':''). ($DBI::errstr?" errstr($DBI::errstr)":'').' Reconnecting');
|
Warning("Not connected to db ($dbh)".($dbh?' ping('.$dbh->ping().')':''). ($DBI::errstr?" errstr($DBI::errstr)":'').' Reconnecting');
|
||||||
$dbh = zmDbConnect();
|
$dbh = zmDbConnect();
|
||||||
|
sleep 10 if !$dbh;
|
||||||
}
|
}
|
||||||
last if $zm_terminate;
|
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_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());
|
$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});
|
sleep($Config{ZM_STATS_UPDATE_INTERVAL});
|
||||||
} # end while (1)
|
} # end while (1)
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,6 @@ if ( !$monitor->{CanMoveMap} ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug("Found monitor for id '$monitor'");
|
|
||||||
exit(-1) if !zmMemVerify($monitor);
|
exit(-1) if !zmMemVerify($monitor);
|
||||||
|
|
||||||
sub Suspend {
|
sub Suspend {
|
||||||
|
|
|
@ -121,6 +121,8 @@ GetOptions(
|
||||||
my $dbh = zmDbConnect(undef, { mysql_multi_statements=>1 } );
|
my $dbh = zmDbConnect(undef, { mysql_multi_statements=>1 } );
|
||||||
$Config{ZM_DB_USER} = $dbUser;
|
$Config{ZM_DB_USER} = $dbUser;
|
||||||
$Config{ZM_DB_PASS} = $dbPass;
|
$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 ( ! ($check || $freshen || $rename || $zoneFix || $migrateEvents || $version) ) {
|
||||||
if ( $Config{ZM_DYN_DB_VERSION} ) {
|
if ( $Config{ZM_DYN_DB_VERSION} ) {
|
||||||
|
@ -384,21 +386,22 @@ if ( $version ) {
|
||||||
my $command = 'mysqldump';
|
my $command = 'mysqldump';
|
||||||
if ( defined($portOrSocket) ) {
|
if ( defined($portOrSocket) ) {
|
||||||
if ( $portOrSocket =~ /^\// ) {
|
if ( $portOrSocket =~ /^\// ) {
|
||||||
$command .= " -S".$portOrSocket;
|
$command .= ' -S'.$portOrSocket;
|
||||||
} else {
|
} else {
|
||||||
$command .= " -h".$host." -P".$portOrSocket;
|
$command .= ' -h'.$host.' -P'.$portOrSocket;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$command .= " -h".$host;
|
$command .= ' -h'.$host;
|
||||||
}
|
}
|
||||||
if ( $dbUser ) {
|
if ( $dbUser ) {
|
||||||
$command .= ' -u'.$dbUser;
|
$command .= ' -u'.$dbUser;
|
||||||
$command .= ' -p"'.$dbPass.'"' if $dbPass;
|
$command .= ' -p\''.$dbPass.'\'' if $dbPass;
|
||||||
}
|
}
|
||||||
my $backup = "@ZM_TMPDIR@/".$Config{ZM_DB_NAME}."-".$version.".dump";
|
my $backup = '@ZM_TMPDIR@/'.$Config{ZM_DB_NAME}.'-'.$version.'.dump';
|
||||||
$command .= " --add-drop-table --databases ".$Config{ZM_DB_NAME}." > ".$backup;
|
$command .= ' --add-drop-table --databases '.$Config{ZM_DB_NAME}.' > '.$backup;
|
||||||
print("Creating backup to $backup. This may take several minutes.\n");
|
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 $output = qx($command);
|
||||||
my $status = $? >> 8;
|
my $status = $? >> 8;
|
||||||
if ( $status || logDebugging() ) {
|
if ( $status || logDebugging() ) {
|
||||||
|
@ -969,7 +972,7 @@ sub patchDB {
|
||||||
my $dbh = shift;
|
my $dbh = shift;
|
||||||
my $version = 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';
|
my $command = 'mysql';
|
||||||
if ( defined($portOrSocket) ) {
|
if ( defined($portOrSocket) ) {
|
||||||
if ( $portOrSocket =~ /^\// ) {
|
if ( $portOrSocket =~ /^\// ) {
|
||||||
|
@ -977,12 +980,12 @@ sub patchDB {
|
||||||
} else {
|
} else {
|
||||||
$command .= ' -h'.$host.' -P'.$portOrSocket;
|
$command .= ' -h'.$host.' -P'.$portOrSocket;
|
||||||
}
|
}
|
||||||
} else {
|
} elsif ( $host ) {
|
||||||
$command .= ' -h'.$host;
|
$command .= ' -h'.$host;
|
||||||
}
|
}
|
||||||
if ( $dbUser ) {
|
if ( $dbUser ) {
|
||||||
$command .= ' -u'.$dbUser;
|
$command .= ' -u'.$dbUser;
|
||||||
$command .= ' -p"'.$dbPass.'"' if $dbPass;
|
$command .= ' -p\''.$dbPass.'\'' if $dbPass;
|
||||||
}
|
}
|
||||||
$command .= ' '.$Config{ZM_DB_NAME}.' < ';
|
$command .= ' '.$Config{ZM_DB_NAME}.' < ';
|
||||||
if ( $updateDir ) {
|
if ( $updateDir ) {
|
||||||
|
|
|
@ -48,11 +48,12 @@ Camera::Camera(
|
||||||
record_audio(p_record_audio),
|
record_audio(p_record_audio),
|
||||||
bytes(0)
|
bytes(0)
|
||||||
{
|
{
|
||||||
|
linesize = width * colours;
|
||||||
pixels = width * height;
|
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",
|
Debug(2, "New camera id: %d width: %d line size: %d height: %d colours: %d subpixelorder: %d capture: %d",
|
||||||
monitor_id, width, height, colours, subpixelorder, capture);
|
monitor_id, width, linesize, height, colours, subpixelorder, capture);
|
||||||
|
|
||||||
monitor = NULL;
|
monitor = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ protected:
|
||||||
Monitor * monitor; // Null on instantiation, set as soon as possible.
|
Monitor * monitor; // Null on instantiation, set as soon as possible.
|
||||||
SourceType type;
|
SourceType type;
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
|
unsigned int linesize;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
unsigned int colours;
|
unsigned int colours;
|
||||||
unsigned int subpixelorder;
|
unsigned int subpixelorder;
|
||||||
|
@ -69,6 +70,7 @@ public:
|
||||||
bool IsLibvlc() const { return type == LIBVLC_SRC; }
|
bool IsLibvlc() const { return type == LIBVLC_SRC; }
|
||||||
bool IscURL() const { return type == CURL_SRC; }
|
bool IscURL() const { return type == CURL_SRC; }
|
||||||
unsigned int Width() const { return width; }
|
unsigned int Width() const { return width; }
|
||||||
|
unsigned int LineSize() const { return linesize; }
|
||||||
unsigned int Height() const { return height; }
|
unsigned int Height() const { return height; }
|
||||||
unsigned int Colours() const { return colours; }
|
unsigned int Colours() const { return colours; }
|
||||||
unsigned int SubpixelOrder() const { return subpixelorder; }
|
unsigned int SubpixelOrder() const { return subpixelorder; }
|
||||||
|
|
|
@ -206,7 +206,12 @@ Event::Event(
|
||||||
/* X264 MP4 video writer */
|
/* X264 MP4 video writer */
|
||||||
if ( monitor->GetOptVideoWriter() == Monitor::X264ENCODE ) {
|
if ( monitor->GetOptVideoWriter() == Monitor::X264ENCODE ) {
|
||||||
#if ZM_HAVE_VIDEOWRITER_X264MP4
|
#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
|
#else
|
||||||
Error("ZoneMinder was not compiled with the X264 MP4 video writer, check dependencies (x264 and mp4v2)");
|
Error("ZoneMinder was not compiled with the X264 MP4 video writer, check dependencies (x264 and mp4v2)");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -807,29 +807,38 @@ Debug(1, "Loading image");
|
||||||
|
|
||||||
if ( send_raw ) {
|
if ( send_raw ) {
|
||||||
#if HAVE_SENDFILE
|
#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 ) {
|
if ( zm_sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size) != (int)filestat.st_size ) {
|
||||||
/* sendfile() failed, use standard way instead */
|
/* sendfile() failed, use standard way instead */
|
||||||
img_buffer_size = fread(img_buffer, 1, sizeof(temp_img_buffer), fdj);
|
img_buffer_size = fread(img_buffer, 1, sizeof(temp_img_buffer), fdj);
|
||||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||||
fclose(fdj); /* Close the file handle */
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
if (
|
||||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
(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 */
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
fclose(fdj); /* Close the file handle */
|
fclose(fdj); /* Close the file handle */
|
||||||
} else {
|
} else {
|
||||||
Debug(3, "Content length: %d", img_buffer_size);
|
Debug(3, "Content length: %d", img_buffer_size);
|
||||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
if (
|
||||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
(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));
|
Error("Unable to send stream frame: %s", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ extern "C" {
|
||||||
#include <libavutil/mathematics.h>
|
#include <libavutil/mathematics.h>
|
||||||
#include <libavutil/avstring.h>
|
#include <libavutil/avstring.h>
|
||||||
#include "libavutil/audio_fifo.h"
|
#include "libavutil/audio_fifo.h"
|
||||||
|
#include "libavutil/imgutils.h"
|
||||||
|
|
||||||
/* LIBAVUTIL_VERSION_CHECK checks for the right version of libav and FFmpeg
|
/* LIBAVUTIL_VERSION_CHECK checks for the right version of libav and FFmpeg
|
||||||
* The original source is vlc (in modules/codec/avcodec/avcommon_compat.h)
|
* The original source is vlc (in modules/codec/avcodec/avcommon_compat.h)
|
||||||
|
|
|
@ -174,6 +174,20 @@ FfmpegCamera::FfmpegCamera(
|
||||||
} else {
|
} else {
|
||||||
Panic("Unexpected colours: %d", colours);
|
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
|
||||||
|
|
||||||
FfmpegCamera::~FfmpegCamera() {
|
FfmpegCamera::~FfmpegCamera() {
|
||||||
|
@ -194,12 +208,12 @@ void FfmpegCamera::Terminate() {
|
||||||
|
|
||||||
int FfmpegCamera::PrimeCapture() {
|
int FfmpegCamera::PrimeCapture() {
|
||||||
if ( mCanCapture ) {
|
if ( mCanCapture ) {
|
||||||
Info("Priming capture from %s, Closing", mPath.c_str());
|
Debug(1, "Priming capture from %s, Closing", mPath.c_str());
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
mVideoStreamId = -1;
|
mVideoStreamId = -1;
|
||||||
mAudioStreamId = -1;
|
mAudioStreamId = -1;
|
||||||
Info("Priming capture from %s", mPath.c_str());
|
Debug(1, "Priming capture from %s", mPath.c_str());
|
||||||
|
|
||||||
return OpenFfmpeg();
|
return OpenFfmpeg();
|
||||||
}
|
}
|
||||||
|
@ -608,16 +622,6 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
mFrame->width = width;
|
mFrame->width = width;
|
||||||
mFrame->height = height;
|
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 HAVE_LIBSWSCALE
|
||||||
if ( !sws_isSupportedInput(mVideoCodecContext->pix_fmt) ) {
|
if ( !sws_isSupportedInput(mVideoCodecContext->pix_fmt) ) {
|
||||||
|
@ -976,10 +980,12 @@ int FfmpegCamera::CaptureAndRecord(
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#if HAVE_LIBAVUTIL_HWCONTEXT_H
|
#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) ) {
|
if ( (ret == AVERROR_INVALIDDATA ) && (hw_pix_fmt != AV_PIX_FMT_NONE) ) {
|
||||||
use_hwaccel = false;
|
use_hwaccel = false;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
zm_av_packet_unref(&packet);
|
zm_av_packet_unref(&packet);
|
||||||
|
@ -1087,11 +1093,18 @@ int FfmpegCamera::transfer_to_image(
|
||||||
int size = av_image_fill_arrays(
|
int size = av_image_fill_arrays(
|
||||||
output_frame->data, output_frame->linesize,
|
output_frame->data, output_frame->linesize,
|
||||||
directbuffer, imagePixFormat, width, height,
|
directbuffer, imagePixFormat, width, height,
|
||||||
(AV_PIX_FMT_RGBA == imagePixFormat ? 32 : 1)
|
alignment
|
||||||
);
|
);
|
||||||
if ( size < 0 ) {
|
if ( size < 0 ) {
|
||||||
Error("Problem setting up data pointers into image %s",
|
Error("Problem setting up data pointers into image %s",
|
||||||
av_make_error_string(size).c_str());
|
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
|
#else
|
||||||
avpicture_fill((AVPicture *)output_frame, directbuffer,
|
avpicture_fill((AVPicture *)output_frame, directbuffer,
|
||||||
|
|
|
@ -46,6 +46,8 @@ class FfmpegCamera : public Camera {
|
||||||
|
|
||||||
int frameCount;
|
int frameCount;
|
||||||
|
|
||||||
|
int alignment; /* ffmpeg wants line sizes to be 32bit aligned. Especially 4.3+ */
|
||||||
|
|
||||||
#if HAVE_LIBAVFORMAT
|
#if HAVE_LIBAVFORMAT
|
||||||
AVFormatContext *mFormatContext;
|
AVFormatContext *mFormatContext;
|
||||||
int mVideoStreamId;
|
int mVideoStreamId;
|
||||||
|
|
|
@ -19,7 +19,7 @@ FFmpeg_Input::~FFmpeg_Input() {
|
||||||
avcodec_close(streams[i].context);
|
avcodec_close(streams[i].context);
|
||||||
streams[i].context = NULL;
|
streams[i].context = NULL;
|
||||||
}
|
}
|
||||||
delete streams;
|
delete[] streams;
|
||||||
streams = NULL;
|
streams = NULL;
|
||||||
}
|
}
|
||||||
if ( frame ) {
|
if ( frame ) {
|
||||||
|
|
396
src/zm_image.cpp
396
src/zm_image.cpp
|
@ -108,6 +108,7 @@ Image::Image() {
|
||||||
if ( !initialised )
|
if ( !initialised )
|
||||||
Initialise();
|
Initialise();
|
||||||
width = 0;
|
width = 0;
|
||||||
|
linesize = 0;
|
||||||
height = 0;
|
height = 0;
|
||||||
pixels = 0;
|
pixels = 0;
|
||||||
colours = 0;
|
colours = 0;
|
||||||
|
@ -125,6 +126,7 @@ Image::Image( const char *filename ) {
|
||||||
if ( !initialised )
|
if ( !initialised )
|
||||||
Initialise();
|
Initialise();
|
||||||
width = 0;
|
width = 0;
|
||||||
|
linesize = 0;
|
||||||
height = 0;
|
height = 0;
|
||||||
pixels = 0;
|
pixels = 0;
|
||||||
colours = 0;
|
colours = 0;
|
||||||
|
@ -139,15 +141,42 @@ Image::Image( const char *filename ) {
|
||||||
update_function_pointers();
|
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 )
|
if ( !initialised )
|
||||||
Initialise();
|
Initialise();
|
||||||
width = p_width;
|
width = p_width;
|
||||||
height = p_height;
|
height = p_height;
|
||||||
pixels = width*height;
|
pixels = width*height;
|
||||||
colours = p_colours;
|
colours = p_colours;
|
||||||
|
linesize = p_width * p_colours;
|
||||||
|
padding = p_padding;
|
||||||
subpixelorder = p_subpixelorder;
|
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;
|
buffer = 0;
|
||||||
holdbuffer = 0;
|
holdbuffer = 0;
|
||||||
if ( p_buffer ) {
|
if ( p_buffer ) {
|
||||||
|
@ -169,18 +198,25 @@ Image::Image(const AVFrame *frame) {
|
||||||
width = frame->width;
|
width = frame->width;
|
||||||
height = frame->height;
|
height = frame->height;
|
||||||
pixels = width*height;
|
pixels = width*height;
|
||||||
|
|
||||||
colours = ZM_COLOUR_RGB32;
|
colours = ZM_COLOUR_RGB32;
|
||||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
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;
|
buffer = 0;
|
||||||
holdbuffer = 0;
|
holdbuffer = 0;
|
||||||
AllocImgBuffer(size);
|
AllocImgBuffer(size);
|
||||||
|
|
||||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||||
av_image_fill_arrays(dest_frame->data, dest_frame->linesize,
|
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
|
#else
|
||||||
avpicture_fill( (AVPicture *)dest_frame, buffer,
|
avpicture_fill( (AVPicture *)dest_frame, buffer,
|
||||||
AV_PIX_FMT_RGBA, width, height);
|
AV_PIX_FMT_RGBA, width, height);
|
||||||
|
@ -212,6 +248,7 @@ Image::Image(const Image &p_image) {
|
||||||
if ( !initialised )
|
if ( !initialised )
|
||||||
Initialise();
|
Initialise();
|
||||||
width = p_image.width;
|
width = p_image.width;
|
||||||
|
linesize = p_image.linesize;
|
||||||
height = p_image.height;
|
height = p_image.height;
|
||||||
pixels = p_image.pixels;
|
pixels = p_image.pixels;
|
||||||
colours = p_image.colours;
|
colours = p_image.colours;
|
||||||
|
@ -232,24 +269,16 @@ Image::~Image() {
|
||||||
/* Should be called as part of program shutdown to free everything */
|
/* Should be called as part of program shutdown to free everything */
|
||||||
void Image::Deinitialise() {
|
void Image::Deinitialise() {
|
||||||
if ( !initialised ) return;
|
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;
|
initialised = false;
|
||||||
if ( readjpg_dcinfo ) {
|
if ( readjpg_dcinfo ) {
|
||||||
jpeg_destroy_decompress(readjpg_dcinfo);
|
jpeg_destroy_decompress(readjpg_dcinfo);
|
||||||
delete readjpg_dcinfo;
|
delete readjpg_dcinfo;
|
||||||
readjpg_dcinfo = 0;
|
readjpg_dcinfo = NULL;
|
||||||
}
|
}
|
||||||
if ( decodejpg_dcinfo ) {
|
if ( decodejpg_dcinfo ) {
|
||||||
jpeg_destroy_decompress(decodejpg_dcinfo);
|
jpeg_destroy_decompress(decodejpg_dcinfo);
|
||||||
delete decodejpg_dcinfo;
|
delete decodejpg_dcinfo;
|
||||||
decodejpg_dcinfo = 0;
|
decodejpg_dcinfo = NULL;
|
||||||
}
|
}
|
||||||
for ( unsigned int quality=0; quality <= 100; quality += 1 ) {
|
for ( unsigned int quality=0; quality <= 100; quality += 1 ) {
|
||||||
if ( writejpg_ccinfo[quality] ) {
|
if ( writejpg_ccinfo[quality] ) {
|
||||||
|
@ -268,7 +297,7 @@ void Image::Deinitialise() {
|
||||||
void Image::Initialise() {
|
void Image::Initialise() {
|
||||||
/* Assign the blend pointer to function */
|
/* Assign the blend pointer to function */
|
||||||
if ( config.fast_image_blends ) {
|
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 */
|
fptr_blend = &sse2_fastblend; /* SSE2 fast blend */
|
||||||
Debug(4, "Blend: Using SSE2 fast blend function");
|
Debug(4, "Blend: Using SSE2 fast blend function");
|
||||||
} else if ( config.cpu_extensions && neonversion >= 1 ) {
|
} else if ( config.cpu_extensions && neonversion >= 1 ) {
|
||||||
|
@ -325,7 +354,7 @@ void Image::Initialise() {
|
||||||
|
|
||||||
/* Assign the delta functions */
|
/* Assign the delta functions */
|
||||||
if ( config.cpu_extensions ) {
|
if ( config.cpu_extensions ) {
|
||||||
if ( sseversion >= 35 ) {
|
if ( sse_version >= 35 ) {
|
||||||
/* SSSE3 available */
|
/* SSSE3 available */
|
||||||
fptr_delta8_rgba = &ssse3_delta8_rgba;
|
fptr_delta8_rgba = &ssse3_delta8_rgba;
|
||||||
fptr_delta8_bgra = &ssse3_delta8_bgra;
|
fptr_delta8_bgra = &ssse3_delta8_bgra;
|
||||||
|
@ -333,7 +362,7 @@ void Image::Initialise() {
|
||||||
fptr_delta8_abgr = &ssse3_delta8_abgr;
|
fptr_delta8_abgr = &ssse3_delta8_abgr;
|
||||||
fptr_delta8_gray8 = &sse2_delta8_gray8;
|
fptr_delta8_gray8 = &sse2_delta8_gray8;
|
||||||
Debug(4, "Delta: Using SSSE3 delta functions");
|
Debug(4, "Delta: Using SSSE3 delta functions");
|
||||||
} else if ( sseversion >= 20 ) {
|
} else if ( sse_version >= 20 ) {
|
||||||
/* SSE2 available */
|
/* SSE2 available */
|
||||||
fptr_delta8_rgba = &sse2_delta8_rgba;
|
fptr_delta8_rgba = &sse2_delta8_rgba;
|
||||||
fptr_delta8_bgra = &sse2_delta8_bgra;
|
fptr_delta8_bgra = &sse2_delta8_bgra;
|
||||||
|
@ -437,7 +466,7 @@ void Image::Initialise() {
|
||||||
|
|
||||||
#if defined(__i386__) && !defined(__x86_64__)
|
#if defined(__i386__) && !defined(__x86_64__)
|
||||||
/* Use SSE2 aligned memory copy? */
|
/* Use SSE2 aligned memory copy? */
|
||||||
if ( config.cpu_extensions && sseversion >= 20 ) {
|
if ( config.cpu_extensions && sse_version >= 20 ) {
|
||||||
fptr_imgbufcpy = &sse2_aligned_memcpy;
|
fptr_imgbufcpy = &sse2_aligned_memcpy;
|
||||||
Debug(4, "Image buffer copy: Using SSE2 aligned memcpy");
|
Debug(4, "Image buffer copy: Using SSE2 aligned memcpy");
|
||||||
} else {
|
} else {
|
||||||
|
@ -449,60 +478,28 @@ void Image::Initialise() {
|
||||||
Debug(4, "Image buffer copy: Using standard memcpy");
|
Debug(4, "Image buffer copy: Using standard memcpy");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Code below relocated from zm_local_camera */
|
|
||||||
Debug( 3, "Setting up static colour tables" );
|
|
||||||
|
|
||||||
y_table = y_table_global;
|
y_table = y_table_global;
|
||||||
uv_table = uv_table_global;
|
uv_table = uv_table_global;
|
||||||
r_v_table = r_v_table_global;
|
r_v_table = r_v_table_global;
|
||||||
g_v_table = g_v_table_global;
|
g_v_table = g_v_table_global;
|
||||||
g_u_table = g_u_table_global;
|
g_u_table = g_u_table_global;
|
||||||
b_u_table = b_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;
|
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 */
|
/* 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);
|
Error("WriteBuffer called with unexpected colours: %d", p_colours);
|
||||||
return NULL;
|
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 ) {
|
if ( p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder ) {
|
||||||
|
|
||||||
unsigned int newsize = (p_width * p_height) * p_colours;
|
unsigned int newsize = (p_width * p_height) * p_colours;
|
||||||
|
|
||||||
if ( buffer == NULL ) {
|
if ( buffer == NULL ) {
|
||||||
|
@ -533,6 +531,7 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
|
||||||
width = p_width;
|
width = p_width;
|
||||||
height = p_height;
|
height = p_height;
|
||||||
colours = p_colours;
|
colours = p_colours;
|
||||||
|
linesize = p_width * p_colours;
|
||||||
subpixelorder = p_subpixelorder;
|
subpixelorder = p_subpixelorder;
|
||||||
pixels = height*width;
|
pixels = height*width;
|
||||||
size = newsize;
|
size = newsize;
|
||||||
|
@ -541,8 +540,18 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
|
||||||
return buffer;
|
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. */
|
/* Assign an existing buffer to the image instead of copying from a source buffer.
|
||||||
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) {
|
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 ) {
|
if ( new_buffer == NULL ) {
|
||||||
Error("Attempt to directly assign buffer from a NULL pointer");
|
Error("Attempt to directly assign buffer from a NULL pointer");
|
||||||
return;
|
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);
|
unsigned int new_buffer_size = ((p_width*p_height)*p_colours);
|
||||||
|
|
||||||
if ( buffer_size < new_buffer_size ) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,13 +583,15 @@ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_heigh
|
||||||
width = p_width;
|
width = p_width;
|
||||||
height = p_height;
|
height = p_height;
|
||||||
colours = p_colours;
|
colours = p_colours;
|
||||||
|
linesize = width * colours;
|
||||||
subpixelorder = p_subpixelorder;
|
subpixelorder = p_subpixelorder;
|
||||||
pixels = height*width;
|
pixels = height*width;
|
||||||
size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size
|
size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size
|
||||||
|
|
||||||
/* Copy into the held buffer */
|
/* Copy into the held buffer */
|
||||||
if ( new_buffer != buffer )
|
if ( new_buffer != buffer ) {
|
||||||
(*fptr_imgbufcpy)(buffer, new_buffer, size);
|
(*fptr_imgbufcpy)(buffer, new_buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
/* Free the new buffer */
|
/* Free the new buffer */
|
||||||
DumpBuffer(new_buffer, p_buffertype);
|
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;
|
width = p_width;
|
||||||
height = p_height;
|
height = p_height;
|
||||||
colours = p_colours;
|
colours = p_colours;
|
||||||
|
linesize = width*colours;
|
||||||
subpixelorder = p_subpixelorder;
|
subpixelorder = p_subpixelorder;
|
||||||
pixels = height*width;
|
pixels = height*width;
|
||||||
size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size
|
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;
|
buffertype = p_buffertype;
|
||||||
buffer = new_buffer;
|
buffer = new_buffer;
|
||||||
}
|
}
|
||||||
|
} // end void Image::AssignDirect
|
||||||
|
|
||||||
}
|
void Image::Assign(
|
||||||
|
const unsigned int p_width,
|
||||||
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) {
|
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;
|
unsigned int new_size = (p_width * p_height) * p_colours;
|
||||||
|
|
||||||
if ( new_buffer == NULL ) {
|
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 )
|
if ( new_buffer != buffer )
|
||||||
(*fptr_imgbufcpy)(buffer, new_buffer, size);
|
(*fptr_imgbufcpy)(buffer, new_buffer, size);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::Assign(const Image &image) {
|
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 ) {
|
if ( image.buffer == NULL ) {
|
||||||
Error("Attempt to assign image with an empty buffer");
|
Error("Attempt to assign image with an empty buffer");
|
||||||
return;
|
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);
|
Error("Attempt to assign image with unexpected colours per pixel: %d", image.colours);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !buffer || image.width != width || image.height != height
|
if ( !buffer
|
||||||
|| image.colours != colours || image.subpixelorder != subpixelorder) {
|
|| image.width != width || image.height != height
|
||||||
|
|| image.colours != colours || image.subpixelorder != subpixelorder
|
||||||
|
|| image.linesize != linesize
|
||||||
|
) {
|
||||||
|
|
||||||
if ( holdbuffer && buffer ) {
|
if ( holdbuffer && buffer ) {
|
||||||
if ( new_size > allocation ) {
|
if ( new_size > allocation ) {
|
||||||
|
@ -686,13 +710,19 @@ void Image::Assign( const Image &image ) {
|
||||||
colours = image.colours;
|
colours = image.colours;
|
||||||
subpixelorder = image.subpixelorder;
|
subpixelorder = image.subpixelorder;
|
||||||
size = new_size;
|
size = new_size;
|
||||||
|
linesize = image.linesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( image.buffer != buffer )
|
if ( image.buffer != buffer )
|
||||||
(*fptr_imgbufcpy)(buffer, image.buffer, size);
|
(*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 ) {
|
if ( colours != ZM_COLOUR_GRAY8 ) {
|
||||||
Panic("Attempt to highlight image edges when colours = %d", colours);
|
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_x = limits ? limits->Hi().X() : width-1;
|
||||||
unsigned int hi_y = limits ? limits->Hi().Y() : height-1;
|
unsigned int hi_y = limits ? limits->Hi().Y() : height-1;
|
||||||
|
|
||||||
if ( p_colours == ZM_COLOUR_GRAY8 )
|
if ( p_colours == ZM_COLOUR_GRAY8 ) {
|
||||||
{
|
for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
|
||||||
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;
|
||||||
const uint8_t* p = buffer + (y * width) + lo_x;
|
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) {
|
||||||
uint8_t* phigh = high_buff + (y * width) + lo_x;
|
|
||||||
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ )
|
|
||||||
{
|
|
||||||
bool edge = false;
|
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 > 0 && !*(p-1) ) edge = true;
|
||||||
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
|
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
|
||||||
if ( !edge && y > 0 && !*(p-width) ) edge = true;
|
if ( !edge && y > 0 && !*(p-width) ) edge = true;
|
||||||
if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
|
if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if ( edge )
|
if ( edge ) {
|
||||||
{
|
|
||||||
*phigh = colour;
|
*phigh = colour;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if ( p_colours == ZM_COLOUR_RGB24 ) {
|
||||||
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;
|
||||||
for ( unsigned int y = lo_y; y <= hi_y; y++ )
|
uint8_t* phigh = high_buff + (((y * linesize) + lo_x) * 3);
|
||||||
{
|
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh += 3 ) {
|
||||||
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 )
|
|
||||||
{
|
|
||||||
bool edge = false;
|
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 > 0 && !*(p-1) ) edge = true;
|
||||||
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
|
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
|
||||||
if ( !edge && y > 0 && !*(p-width) ) edge = true;
|
if ( !edge && y > 0 && !*(p-width) ) edge = true;
|
||||||
if ( !edge && y < (height-1) && !*(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);
|
RED_PTR_RGBA(phigh) = RED_VAL_RGBA(colour);
|
||||||
GREEN_PTR_RGBA(phigh) = GREEN_VAL_RGBA(colour);
|
GREEN_PTR_RGBA(phigh) = GREEN_VAL_RGBA(colour);
|
||||||
BLUE_PTR_RGBA(phigh) = BLUE_VAL_RGBA(colour);
|
BLUE_PTR_RGBA(phigh) = BLUE_VAL_RGBA(colour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if ( p_colours == ZM_COLOUR_RGB32 ) {
|
||||||
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;
|
||||||
for ( unsigned int y = lo_y; y <= hi_y; y++ )
|
Rgb* phigh = (Rgb*)(high_buff + (((y * linesize) + lo_x) * 4));
|
||||||
{
|
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) {
|
||||||
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++ )
|
|
||||||
{
|
|
||||||
bool edge = false;
|
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 > 0 && !*(p-1) ) edge = true;
|
||||||
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
|
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
|
||||||
if ( !edge && y > 0 && !*(p-width) ) edge = true;
|
if ( !edge && y > 0 && !*(p-width) ) edge = true;
|
||||||
if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
|
if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if ( edge )
|
if ( edge ) {
|
||||||
{
|
|
||||||
*phigh = colour;
|
*phigh = colour;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return( high_image );
|
return high_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Image::ReadRaw(const char *filename) {
|
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 ) {
|
switch ( p_colours ) {
|
||||||
case ZM_COLOUR_GRAY8:
|
case ZM_COLOUR_GRAY8:
|
||||||
{
|
|
||||||
cinfo->out_color_space = JCS_GRAYSCALE;
|
cinfo->out_color_space = JCS_GRAYSCALE;
|
||||||
new_colours = ZM_COLOUR_GRAY8;
|
new_colours = ZM_COLOUR_GRAY8;
|
||||||
new_subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
new_subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case ZM_COLOUR_RGB32:
|
case ZM_COLOUR_RGB32:
|
||||||
{
|
|
||||||
#ifdef JCS_EXTENSIONS
|
#ifdef JCS_EXTENSIONS
|
||||||
new_colours = ZM_COLOUR_RGB32;
|
new_colours = ZM_COLOUR_RGB32;
|
||||||
if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
|
if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
|
||||||
|
@ -914,10 +933,8 @@ bool Image::ReadJpeg(const char *filename, unsigned int p_colours, unsigned int
|
||||||
#else
|
#else
|
||||||
Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead.");
|
Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead.");
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
case ZM_COLOUR_RGB24:
|
case ZM_COLOUR_RGB24:
|
||||||
default:
|
default:
|
||||||
{
|
|
||||||
new_colours = ZM_COLOUR_RGB24;
|
new_colours = ZM_COLOUR_RGB24;
|
||||||
if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGR ) {
|
if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGR ) {
|
||||||
#ifdef JCS_EXTENSIONS
|
#ifdef JCS_EXTENSIONS
|
||||||
|
@ -941,8 +958,7 @@ cinfo->out_color_space = JCS_RGB;
|
||||||
new_subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
new_subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
} // end switch p_colours
|
||||||
}
|
|
||||||
|
|
||||||
if ( WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL ) {
|
if ( WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL ) {
|
||||||
Error("Failed requesting writeable buffer for reading JPEG image.");
|
Error("Failed requesting writeable buffer for reading JPEG image.");
|
||||||
|
@ -953,11 +969,10 @@ cinfo->out_color_space = JCS_RGB;
|
||||||
|
|
||||||
jpeg_start_decompress(cinfo);
|
jpeg_start_decompress(cinfo);
|
||||||
|
|
||||||
JSAMPROW row_pointer; /* pointer to a single row */
|
JSAMPROW row_pointer = buffer;
|
||||||
int row_stride = width * colours; /* physical row width in buffer */
|
|
||||||
while ( cinfo->output_scanline < cinfo->output_height ) {
|
while ( cinfo->output_scanline < cinfo->output_height ) {
|
||||||
row_pointer = &buffer[cinfo->output_scanline * row_stride];
|
|
||||||
jpeg_read_scanlines(cinfo, &row_pointer, 1);
|
jpeg_read_scanlines(cinfo, &row_pointer, 1);
|
||||||
|
row_pointer += linesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
jpeg_finish_decompress(cinfo);
|
jpeg_finish_decompress(cinfo);
|
||||||
|
@ -971,21 +986,22 @@ cinfo->out_color_space = JCS_RGB;
|
||||||
// Note quality=zero means default
|
// Note quality=zero means default
|
||||||
|
|
||||||
bool Image::WriteJpeg(const char *filename, int quality_override) const {
|
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 {
|
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 {
|
bool Image::WriteJpeg(const char *filename, bool on_blocking_abort) const {
|
||||||
return Image::WriteJpeg(filename, 0, (timeval){0,0}, on_blocking_abort);
|
return Image::WriteJpeg(filename, 0, (timeval){0,0}, on_blocking_abort);
|
||||||
}
|
}
|
||||||
bool Image::WriteJpeg(const char *filename, struct timeval timestamp) const {
|
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 {
|
bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval timestamp) const {
|
||||||
return Image::WriteJpeg(filename, quality_override, timestamp, false);
|
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 {
|
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) ) {
|
if ( config.colour_jpeg_files && (colours == ZM_COLOUR_GRAY8) ) {
|
||||||
Image temp_image(*this);
|
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];
|
struct jpeg_compress_struct *cinfo = writejpg_ccinfo[quality];
|
||||||
FILE *outfile = NULL;
|
FILE *outfile = NULL;
|
||||||
static int raw_fd = 0;
|
static int raw_fd = 0;
|
||||||
bool need_create_comp = false;
|
|
||||||
raw_fd = 0;
|
raw_fd = 0;
|
||||||
|
|
||||||
if ( !cinfo ) {
|
if ( !cinfo ) {
|
||||||
cinfo = writejpg_ccinfo[quality] = new jpeg_compress_struct;
|
cinfo = writejpg_ccinfo[quality] = new jpeg_compress_struct;
|
||||||
cinfo->err = jpeg_std_error(&jpg_err.pub);
|
cinfo->err = jpeg_std_error(&jpg_err.pub);
|
||||||
jpeg_create_compress(cinfo);
|
jpeg_create_compress(cinfo);
|
||||||
need_create_comp = true;
|
|
||||||
}
|
}
|
||||||
if ( !on_blocking_abort ) {
|
if ( !on_blocking_abort ) {
|
||||||
jpg_err.pub.error_exit = zm_jpeg_error_exit;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( need_create_comp )
|
|
||||||
jpeg_create_compress(cinfo);
|
|
||||||
|
|
||||||
if ( !on_blocking_abort ) {
|
if ( !on_blocking_abort ) {
|
||||||
if ( (outfile = fopen(filename, "wb")) == NULL ) {
|
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:
|
case ZM_COLOUR_RGB32:
|
||||||
#ifdef JCS_EXTENSIONS
|
#ifdef JCS_EXTENSIONS
|
||||||
cinfo->input_components = 4;
|
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;
|
cinfo->in_color_space = JCS_EXT_BGRX;
|
||||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) {
|
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) {
|
||||||
cinfo->in_color_space = JCS_EXT_XRGB;
|
cinfo->in_color_space = JCS_EXT_XRGB;
|
||||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) {
|
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) {
|
||||||
cinfo->in_color_space = JCS_EXT_XBGR;
|
cinfo->in_color_space = JCS_EXT_XBGR;
|
||||||
} else {
|
} else {
|
||||||
|
Warning("Unknwon subpixelorder %d", subpixelorder);
|
||||||
/* Assume RGBA */
|
/* Assume RGBA */
|
||||||
cinfo->in_color_space = JCS_EXT_RGBX;
|
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));
|
jpeg_write_marker(cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes));
|
||||||
}
|
}
|
||||||
|
|
||||||
JSAMPROW row_pointer; /* pointer to a single row */
|
JSAMPROW row_pointer = buffer; /* pointer to a single row */
|
||||||
int row_stride = cinfo->image_width * colours; /* physical row width in buffer */
|
|
||||||
while ( cinfo->next_scanline < cinfo->image_height ) {
|
while ( cinfo->next_scanline < cinfo->image_height ) {
|
||||||
row_pointer = &buffer[cinfo->next_scanline * row_stride];
|
|
||||||
jpeg_write_scanlines(cinfo, &row_pointer, 1);
|
jpeg_write_scanlines(cinfo, &row_pointer, 1);
|
||||||
|
row_pointer += linesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
jpeg_finish_compress(cinfo);
|
jpeg_finish_compress(cinfo);
|
||||||
|
|
||||||
fclose(outfile);
|
fclose(outfile);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1252,11 +1264,10 @@ cinfo->out_color_space = JCS_RGB;
|
||||||
|
|
||||||
jpeg_start_decompress(cinfo);
|
jpeg_start_decompress(cinfo);
|
||||||
|
|
||||||
JSAMPROW row_pointer; /* pointer to a single row */
|
JSAMPROW row_pointer = buffer; /* pointer to a single row */
|
||||||
int row_stride = width * colours; /* physical row width in buffer */
|
|
||||||
while ( cinfo->output_scanline < cinfo->output_height ) {
|
while ( cinfo->output_scanline < cinfo->output_height ) {
|
||||||
row_pointer = &buffer[cinfo->output_scanline * row_stride];
|
|
||||||
jpeg_read_scanlines(cinfo, &row_pointer, 1);
|
jpeg_read_scanlines(cinfo, &row_pointer, 1);
|
||||||
|
row_pointer += linesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
jpeg_finish_decompress(cinfo);
|
jpeg_finish_decompress(cinfo);
|
||||||
|
@ -1296,13 +1307,16 @@ bool Image::EncodeJpeg(JOCTET *outbuffer, int *outbuffer_size, int quality_overr
|
||||||
case ZM_COLOUR_RGB32:
|
case ZM_COLOUR_RGB32:
|
||||||
#ifdef JCS_EXTENSIONS
|
#ifdef JCS_EXTENSIONS
|
||||||
cinfo->input_components = 4;
|
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;
|
cinfo->in_color_space = JCS_EXT_BGRX;
|
||||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) {
|
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) {
|
||||||
cinfo->in_color_space = JCS_EXT_XRGB;
|
cinfo->in_color_space = JCS_EXT_XRGB;
|
||||||
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) {
|
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) {
|
||||||
cinfo->in_color_space = JCS_EXT_XBGR;
|
cinfo->in_color_space = JCS_EXT_XBGR;
|
||||||
} else {
|
} else {
|
||||||
|
Warning("unknown subpixelorder %d", subpixelorder);
|
||||||
/* Assume RGBA */
|
/* Assume RGBA */
|
||||||
cinfo->in_color_space = JCS_EXT_RGBX;
|
cinfo->in_color_space = JCS_EXT_RGBX;
|
||||||
}
|
}
|
||||||
|
@ -1343,11 +1357,10 @@ cinfo->out_color_space = JCS_RGB;
|
||||||
|
|
||||||
jpeg_start_compress(cinfo, TRUE);
|
jpeg_start_compress(cinfo, TRUE);
|
||||||
|
|
||||||
JSAMPROW row_pointer; /* pointer to a single row */
|
JSAMPROW row_pointer = buffer;
|
||||||
int row_stride = cinfo->image_width * colours; /* physical row width in buffer */
|
|
||||||
while ( cinfo->next_scanline < cinfo->image_height ) {
|
while ( cinfo->next_scanline < cinfo->image_height ) {
|
||||||
row_pointer = &buffer[cinfo->next_scanline * row_stride];
|
|
||||||
jpeg_write_scanlines(cinfo, &row_pointer, 1);
|
jpeg_write_scanlines(cinfo, &row_pointer, 1);
|
||||||
|
row_pointer += linesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
jpeg_finish_compress(cinfo);
|
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 ) {
|
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);
|
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) ) ) {
|
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;
|
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;
|
unsigned int new_stride = new_width * colours;
|
||||||
for ( unsigned int y = lo_y, ny = 0; y <= hi_y; y++, ny++ ) {
|
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];
|
unsigned char *pnbuf = &new_buffer[(ny*new_width)*colours];
|
||||||
memcpy( pnbuf, pbuf, new_stride );
|
memcpy( pnbuf, pbuf, new_stride );
|
||||||
}
|
}
|
||||||
|
@ -1631,8 +1645,7 @@ void Image::Overlay( const Image &image, unsigned int x, unsigned int y ) {
|
||||||
} else {
|
} else {
|
||||||
Error("Overlay called with unexpected colours: %d", colours);
|
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 ) {
|
void Image::Blend( const Image &image, int transparency ) {
|
||||||
#ifdef ZM_IMAGE_PROFILING
|
#ifdef ZM_IMAGE_PROFILING
|
||||||
|
@ -1771,7 +1784,7 @@ Image *Image::Highlight( unsigned int n_images, Image *images[], const Rgb thres
|
||||||
return result;
|
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 {
|
void Image::Delta( const Image &image, Image* targetimage) const {
|
||||||
#ifdef ZM_IMAGE_PROFILING
|
#ifdef ZM_IMAGE_PROFILING
|
||||||
struct timespec start,end,diff;
|
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 x = (width - (max_line_len * ZM_CHAR_WIDTH) ) / 2;
|
||||||
int y = (height - (line_no * LINE_HEIGHT) ) / 2;
|
int y = (height - (line_no * LINE_HEIGHT) ) / 2;
|
||||||
return( Coord( x, y ) );
|
return Coord(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RGB32 compatible: complete */
|
/* 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;
|
unsigned char *temp_ptr = ptr;
|
||||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||||
int f;
|
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];
|
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];
|
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++ ) {
|
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 ( f & (zm_text_bitmask >> i) ) {
|
||||||
if ( !fg_trans )
|
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;
|
unsigned char *temp_ptr = ptr;
|
||||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||||
int f;
|
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];
|
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];
|
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 ) {
|
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 ( f & (zm_text_bitmask >> i) ) {
|
||||||
if ( !fg_trans ) {
|
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;
|
Rgb* temp_ptr = (Rgb*)ptr;
|
||||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||||
int f;
|
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];
|
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];
|
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++ ) {
|
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 ( f & (zm_text_bitmask >> i) ) {
|
||||||
if ( !fg_trans ) {
|
if ( !fg_trans ) {
|
||||||
|
@ -2033,7 +2073,7 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Panic("Annotate called with unexpected colours: %d",colours);
|
Error("Annotate called with unexpected colours: %d", colours);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2123,7 +2163,7 @@ void Image::DeColourise() {
|
||||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||||
size = width * height;
|
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 */
|
/* Use SSSE3 functions */
|
||||||
switch (subpixelorder) {
|
switch (subpixelorder) {
|
||||||
case ZM_SUBPIX_ORDER_BGRA:
|
case ZM_SUBPIX_ORDER_BGRA:
|
||||||
|
@ -2317,9 +2357,7 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) {
|
||||||
|
|
||||||
double grad;
|
double grad;
|
||||||
|
|
||||||
//Debug( 9, "dx: %.2lf, dy: %.2lf", dx, dy );
|
|
||||||
if ( fabs(dx) <= fabs(dy) ) {
|
if ( fabs(dx) <= fabs(dy) ) {
|
||||||
//Debug( 9, "dx <= dy" );
|
|
||||||
if ( y1 != y2 )
|
if ( y1 != y2 )
|
||||||
grad = dx/dy;
|
grad = dx/dy;
|
||||||
else
|
else
|
||||||
|
@ -2329,9 +2367,7 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) {
|
||||||
int y, yinc = (y1<y2)?1:-1;
|
int y, yinc = (y1<y2)?1:-1;
|
||||||
grad *= yinc;
|
grad *= yinc;
|
||||||
if ( colours == ZM_COLOUR_GRAY8 ) {
|
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 ) {
|
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;
|
buffer[(y*width)+int(round(x))] = colour;
|
||||||
}
|
}
|
||||||
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
||||||
|
@ -2418,7 +2454,8 @@ void Image::Fill( Rgb colour, int density, const Polygon &polygon ) {
|
||||||
#ifndef ZM_DBG_OFF
|
#ifndef ZM_DBG_OFF
|
||||||
if ( logLevel() >= Logger::DEBUG9 ) {
|
if ( logLevel() >= Logger::DEBUG9 ) {
|
||||||
for ( int i = 0; i < n_global_edges; i++ ) {
|
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
|
#endif
|
||||||
|
@ -2445,7 +2482,8 @@ void Image::Fill( Rgb colour, int density, const Polygon &polygon ) {
|
||||||
#ifndef ZM_DBG_OFF
|
#ifndef ZM_DBG_OFF
|
||||||
if ( logLevel() >= Logger::DEBUG9 ) {
|
if ( logLevel() >= Logger::DEBUG9 ) {
|
||||||
for ( int i = 0; i < n_active_edges; i++ ) {
|
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
|
#endif
|
||||||
|
@ -2503,18 +2541,12 @@ void Image::Fill( Rgb colour, const Polygon &polygon ) {
|
||||||
Fill(colour, 1, polygon);
|
Fill(colour, 1, polygon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RGB32 compatible: complete */
|
|
||||||
void Image::Rotate(int angle) {
|
void Image::Rotate(int angle) {
|
||||||
|
|
||||||
angle %= 360;
|
angle %= 360;
|
||||||
|
|
||||||
if ( !angle ) {
|
if ( !angle || angle%90 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( angle%90 ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int new_height = height;
|
unsigned int new_height = height;
|
||||||
unsigned int new_width = width;
|
unsigned int new_width = width;
|
||||||
uint8_t* rotate_buffer = AllocBuffer(size);
|
uint8_t* rotate_buffer = AllocBuffer(size);
|
||||||
|
@ -2538,17 +2570,17 @@ void Image::Rotate( int angle ) {
|
||||||
}
|
}
|
||||||
} else if ( colours == ZM_COLOUR_RGB32 ) {
|
} else if ( colours == ZM_COLOUR_RGB32 ) {
|
||||||
Rgb* s_rptr = (Rgb*)s_ptr;
|
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));
|
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 = *s_rptr++;
|
||||||
d_rptr += new_width;
|
d_rptr += new_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else /* Assume RGB24 */ {
|
} 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);
|
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 = *s_ptr++;
|
||||||
*(d_ptr+1) = *s_ptr++;
|
*(d_ptr+1) = *s_ptr++;
|
||||||
*(d_ptr+2) = *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);
|
AssignDirect(new_width, new_height, colours, subpixelorder, rotate_buffer, size, ZM_BUFTYPE_ZM);
|
||||||
}
|
} // void Image::Rotate(int angle)
|
||||||
|
|
||||||
/* RGB32 compatible: complete */
|
/* RGB32 compatible: complete */
|
||||||
void Image::Flip( bool leftright ) {
|
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);
|
AssignDirect(width, height, colours, subpixelorder, flip_buffer, size, ZM_BUFTYPE_ZM);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::Scale(unsigned int factor) {
|
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_width = (width*factor)/ZM_SCALE_BASE;
|
||||||
unsigned int new_height = (height*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;
|
size_t scale_buffer_size = (new_width+1) * (new_height+1) * colours;
|
||||||
|
|
||||||
uint8_t* scale_buffer = AllocBuffer(scale_buffer_size);
|
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_h_index = 0;
|
||||||
unsigned int last_w_index = 0;
|
unsigned int last_w_index = 0;
|
||||||
unsigned int h_index;
|
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_count += factor;
|
||||||
h_index = h_count/ZM_SCALE_BASE;
|
h_index = h_count/ZM_SCALE_BASE;
|
||||||
if ( h_index > last_h_index ) {
|
if ( h_index > last_h_index ) {
|
||||||
|
@ -2756,7 +2788,7 @@ void Image::Scale( unsigned int factor ) {
|
||||||
last_w_index = 0;
|
last_w_index = 0;
|
||||||
|
|
||||||
unsigned char *ps = &buffer[y*wc];
|
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_count += factor;
|
||||||
w_index = w_count/ZM_SCALE_BASE;
|
w_index = w_count/ZM_SCALE_BASE;
|
||||||
|
|
||||||
|
@ -2774,10 +2806,8 @@ void Image::Scale( unsigned int factor ) {
|
||||||
}
|
}
|
||||||
new_width = last_w_index;
|
new_width = last_w_index;
|
||||||
new_height = last_h_index;
|
new_height = last_h_index;
|
||||||
}
|
} // end foreach line
|
||||||
|
|
||||||
AssignDirect(new_width, new_height, colours, subpixelorder, scale_buffer, scale_buffer_size, ZM_BUFTYPE_ZM);
|
AssignDirect(new_width, new_height, colours, subpixelorder, scale_buffer, scale_buffer_size, ZM_BUFTYPE_ZM);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::Deinterlace_Discard() {
|
void Image::Deinterlace_Discard() {
|
||||||
|
@ -2818,7 +2848,6 @@ void Image::Deinterlace_Discard() {
|
||||||
} else {
|
} else {
|
||||||
Error("Deinterlace called with unexpected colours: %d", colours);
|
Error("Deinterlace called with unexpected colours: %d", colours);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::Deinterlace_Linear() {
|
void Image::Deinterlace_Linear() {
|
||||||
|
@ -3619,6 +3648,7 @@ __attribute__((noinline)) void fast_delta8_argb(const uint8_t* col1, const uint8
|
||||||
result += 4;
|
result += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noinline)) void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) {
|
__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 */
|
/* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */
|
||||||
int r,g,b;
|
int r,g,b;
|
||||||
|
|
|
@ -152,9 +152,11 @@ protected:
|
||||||
static struct zm_error_mgr jpg_err;
|
static struct zm_error_mgr jpg_err;
|
||||||
|
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
|
unsigned int linesize;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
unsigned int pixels;
|
unsigned int pixels;
|
||||||
unsigned int colours;
|
unsigned int colours;
|
||||||
|
unsigned int padding;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
unsigned int subpixelorder;
|
unsigned int subpixelorder;
|
||||||
unsigned long allocation;
|
unsigned long allocation;
|
||||||
|
@ -166,14 +168,17 @@ protected:
|
||||||
public:
|
public:
|
||||||
Image();
|
Image();
|
||||||
explicit Image(const char *filename);
|
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 Image &p_image );
|
||||||
explicit Image( const AVFrame *frame );
|
explicit Image( const AVFrame *frame );
|
||||||
|
|
||||||
~Image();
|
~Image();
|
||||||
static void Initialise();
|
static void Initialise();
|
||||||
static void Deinitialise();
|
static void Deinitialise();
|
||||||
|
|
||||||
inline unsigned int Width() const { return width; }
|
inline unsigned int Width() const { return width; }
|
||||||
|
inline unsigned int LineSize() const { return linesize; }
|
||||||
inline unsigned int Height() const { return height; }
|
inline unsigned int Height() const { return height; }
|
||||||
inline unsigned int Pixels() const { return pixels; }
|
inline unsigned int Pixels() const { return pixels; }
|
||||||
inline unsigned int Colours() const { return colours; }
|
inline unsigned int Colours() const { return colours; }
|
||||||
|
@ -182,7 +187,7 @@ public:
|
||||||
|
|
||||||
/* Internal buffer should not be modified from functions outside of this class */
|
/* 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() 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 */
|
/* 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);
|
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 )
|
if ( !holdbuffer )
|
||||||
DumpImgBuffer();
|
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 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) {
|
inline void CopyBuffer(const Image &image) {
|
||||||
Assign(image);
|
Assign(image);
|
||||||
|
|
|
@ -504,7 +504,7 @@ LocalCamera::LocalCamera(
|
||||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||||
} else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8 ) {
|
} else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8 ) {
|
||||||
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
|
/* 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;
|
conversion_fptr = &ssse3_convert_yuyv_gray8;
|
||||||
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
||||||
} else {
|
} else {
|
||||||
|
@ -616,7 +616,7 @@ LocalCamera::LocalCamera(
|
||||||
}
|
}
|
||||||
} else if ( (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_GRAY8 ) {
|
} else if ( (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_GRAY8 ) {
|
||||||
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
|
/* 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;
|
conversion_fptr = &ssse3_convert_yuyv_gray8;
|
||||||
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -131,7 +131,7 @@ Monitor::MonitorLink::~MonitorLink() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Monitor::MonitorLink::connect() {
|
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 );
|
last_connect_time = time( 0 );
|
||||||
|
|
||||||
mem_size = sizeof(SharedData) + sizeof(TriggerData);
|
mem_size = sizeof(SharedData) + sizeof(TriggerData);
|
||||||
|
@ -379,6 +379,7 @@ Monitor::Monitor(
|
||||||
|
|
||||||
strncpy(event_prefix, p_event_prefix, sizeof(event_prefix)-1);
|
strncpy(event_prefix, p_event_prefix, sizeof(event_prefix)-1);
|
||||||
strncpy(label_format, p_label_format, sizeof(label_format)-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
|
// Change \n to actual line feeds
|
||||||
char *token_ptr = label_format;
|
char *token_ptr = label_format;
|
||||||
|
@ -531,6 +532,7 @@ Monitor::Monitor(
|
||||||
shared_data->last_write_index, shared_data->last_write_time );
|
shared_data->last_write_index, shared_data->last_write_time );
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(),
|
ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(),
|
||||||
image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize());
|
image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize());
|
||||||
adaptive_skip = true;
|
adaptive_skip = true;
|
||||||
|
@ -605,7 +607,7 @@ bool Monitor::connect() {
|
||||||
if ( mem_ptr == MAP_FAILED )
|
if ( mem_ptr == MAP_FAILED )
|
||||||
Fatal("Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno);
|
Fatal("Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno);
|
||||||
if ( mem_ptr == NULL ) {
|
if ( mem_ptr == NULL ) {
|
||||||
Error("mmap gave a null address:");
|
Error("mmap gave a NULL address:");
|
||||||
} else {
|
} else {
|
||||||
Debug(3, "mmapped to %p", mem_ptr);
|
Debug(3, "mmapped to %p", mem_ptr);
|
||||||
}
|
}
|
||||||
|
@ -1406,9 +1408,6 @@ bool Monitor::Analyse() {
|
||||||
score += trigger_data->trigger_score;
|
score += trigger_data->trigger_score;
|
||||||
Debug(1, "Triggered on score += %d => %d", trigger_data->trigger_score, score);
|
Debug(1, "Triggered on score += %d => %d", trigger_data->trigger_score, score);
|
||||||
if ( !event ) {
|
if ( !event ) {
|
||||||
// How could it have a length already?
|
|
||||||
//if ( cause.length() )
|
|
||||||
//cause += ", ";
|
|
||||||
cause += trigger_data->trigger_cause;
|
cause += trigger_data->trigger_cause;
|
||||||
}
|
}
|
||||||
Event::StringSet noteSet;
|
Event::StringSet noteSet;
|
||||||
|
@ -1488,6 +1487,7 @@ bool Monitor::Analyse() {
|
||||||
score += 50;
|
score += 50;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Debug(1, "Linked monitor %d %d is not connected. Connecting.", i, linked_monitors[i]->Id());
|
||||||
linked_monitors[i]->connect();
|
linked_monitors[i]->connect();
|
||||||
}
|
}
|
||||||
} // end foreach linked_monit
|
} // end foreach linked_monit
|
||||||
|
@ -1502,7 +1502,7 @@ bool Monitor::Analyse() {
|
||||||
|
|
||||||
if ( section_length
|
if ( section_length
|
||||||
&& ( ( timestamp->tv_sec - video_store_data->recording.tv_sec ) >= 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",
|
Info("%s: %03d - Closing event %" PRIu64 ", section end forced %d - %d = %d >= %d",
|
||||||
name, image_count, event->Id(),
|
name, image_count, event->Id(),
|
||||||
|
@ -1515,7 +1515,6 @@ bool Monitor::Analyse() {
|
||||||
} // end if event
|
} // end if event
|
||||||
|
|
||||||
if ( !event ) {
|
if ( !event ) {
|
||||||
|
|
||||||
// Create event
|
// Create event
|
||||||
event = new Event(this, *timestamp, "Continuous", noteSetMap, videoRecording);
|
event = new Event(this, *timestamp, "Continuous", noteSetMap, videoRecording);
|
||||||
shared_data->last_event = event->Id();
|
shared_data->last_event = event->Id();
|
||||||
|
@ -1529,7 +1528,6 @@ bool Monitor::Analyse() {
|
||||||
if ( state == IDLE ) {
|
if ( state == IDLE ) {
|
||||||
shared_data->state = state = TAPE;
|
shared_data->state = state = TAPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end if ! event
|
} // end if ! event
|
||||||
} // end if function == RECORD || function == MOCORD)
|
} // end if function == RECORD || function == MOCORD)
|
||||||
} // end if !signal_change && signal
|
} // end if !signal_change && signal
|
||||||
|
@ -1553,7 +1551,6 @@ bool Monitor::Analyse() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( (!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count-1) ) {
|
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
|
// lets construct alarm cause. It will contain cause + names of zones alarmed
|
||||||
std::string alarm_cause = "";
|
std::string alarm_cause = "";
|
||||||
for ( int i=0; i < n_zones; i++ ) {
|
for ( int i=0; i < n_zones; i++ ) {
|
||||||
|
@ -1638,6 +1635,7 @@ bool Monitor::Analyse() {
|
||||||
event->SavePreAlarmFrames();
|
event->SavePreAlarmFrames();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
shared_data->state = state = ALARM;
|
||||||
} else if ( state != PREALARM ) {
|
} else if ( state != PREALARM ) {
|
||||||
Info("%s: %03d - Gone into prealarm state", name, image_count);
|
Info("%s: %03d - Gone into prealarm state", name, image_count);
|
||||||
shared_data->state = state = PREALARM;
|
shared_data->state = state = PREALARM;
|
||||||
|
@ -1697,17 +1695,10 @@ bool Monitor::Analyse() {
|
||||||
} // end if zone is alarmed
|
} // end if zone is alarmed
|
||||||
} // end foreach zone
|
} // end foreach zone
|
||||||
|
|
||||||
if ( got_anal_image ) {
|
|
||||||
if ( state == PREALARM )
|
if ( state == PREALARM )
|
||||||
Event::AddPreAlarmFrame(snap_image, *timestamp, score, &alarm_image);
|
Event::AddPreAlarmFrame(snap_image, *timestamp, score, (got_anal_image?&alarm_image:NULL));
|
||||||
else
|
else
|
||||||
event->AddFrame(snap_image, *timestamp, score, &alarm_image);
|
event->AddFrame(snap_image, *timestamp, score, (got_anal_image?&alarm_image:NULL));
|
||||||
} else {
|
|
||||||
if ( state == PREALARM )
|
|
||||||
Event::AddPreAlarmFrame(snap_image, *timestamp, score);
|
|
||||||
else
|
|
||||||
event->AddFrame(snap_image, *timestamp, score);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Not doing alarm frame storage
|
// Not doing alarm frame storage
|
||||||
if ( state == PREALARM ) {
|
if ( state == PREALARM ) {
|
||||||
|
@ -1743,7 +1734,6 @@ bool Monitor::Analyse() {
|
||||||
//set up video store data
|
//set up video store data
|
||||||
snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile());
|
snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile());
|
||||||
video_store_data->recording = event->StartTime();
|
video_store_data->recording = event->StartTime();
|
||||||
|
|
||||||
}
|
}
|
||||||
} // end if event
|
} // end if event
|
||||||
|
|
||||||
|
|
|
@ -220,7 +220,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isConnected() const {
|
inline bool isConnected() const {
|
||||||
return( connected );
|
return connected && shared_data->valid;
|
||||||
}
|
}
|
||||||
inline time_t getLastConnectTime() const {
|
inline time_t getLastConnectTime() const {
|
||||||
return( last_connect_time );
|
return( last_connect_time );
|
||||||
|
@ -463,7 +463,8 @@ public:
|
||||||
|
|
||||||
int GetOptSaveJPEGs() const { return savejpegs; }
|
int GetOptSaveJPEGs() const { return savejpegs; }
|
||||||
VideoWriter GetOptVideoWriter() const { return videowriter; }
|
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; }
|
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; }
|
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; }
|
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);
|
gettimeofday(&frameStartTime, NULL);
|
||||||
|
|
||||||
fputs("--ZoneMinderFrame\r\nContent-Type: image/jpeg\r\n", stdout);
|
fputs("--ZoneMinderFrame\r\nContent-Type: image/jpeg\r\n", stdout);
|
||||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
if (
|
||||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
(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 ( !zm_terminate )
|
||||||
Warning("Unable to send stream frame: %s", strerror(errno));
|
Warning("Unable to send stream frame: %s", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
|
@ -410,8 +413,11 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
|
||||||
Error("Unexpected frame type %d", type);
|
Error("Unexpected frame type %d", type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
if (
|
||||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
(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 ( !zm_terminate ) {
|
||||||
// If the pipe was closed, we will get signalled SIGPIPE to exit, which will set 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));
|
Warning("Unable to send stream frame: %s", strerror(errno));
|
||||||
|
|
|
@ -618,8 +618,8 @@ int RemoteCameraHttp::GetResponse() {
|
||||||
static char *content_type_header;
|
static char *content_type_header;
|
||||||
static char *boundary_header;
|
static char *boundary_header;
|
||||||
static char *authenticate_header;
|
static char *authenticate_header;
|
||||||
static char subcontent_length_header[32];
|
static char subcontent_length_header[33];
|
||||||
static char subcontent_type_header[64];
|
static char subcontent_type_header[65];
|
||||||
|
|
||||||
static char http_version[16];
|
static char http_version[16];
|
||||||
static char status_code[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) ) {
|
if ( !boundary_header && (strncasecmp(subheader_ptr, content_boundary, content_boundary_len) == 0) ) {
|
||||||
boundary_header = subheader_ptr;
|
boundary_header = subheader_ptr;
|
||||||
Debug(4, "Got boundary subheader '%s'", 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) ) {
|
} else if (
|
||||||
strncpy( subcontent_length_header, subheader_ptr+content_length_match_len, sizeof(subcontent_length_header) );
|
!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';
|
*(subcontent_length_header+strcspn(subcontent_length_header, "\r\n")) = '\0';
|
||||||
Debug(4, "Got content length subheader '%s'", subcontent_length_header);
|
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) ) {
|
} 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';
|
*(subcontent_type_header+strcspn(subcontent_type_header, "\r\n")) = '\0';
|
||||||
Debug(4, "Got content type subheader '%s'", subcontent_type_header);
|
Debug(4, "Got content type subheader '%s'", subcontent_type_header);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned int sseversion = 0;
|
unsigned int sse_version = 0;
|
||||||
unsigned int neonversion = 0;
|
unsigned int neonversion = 0;
|
||||||
|
|
||||||
std::string trimSet(std::string str, std::string trimset) {
|
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 all spaces or empty return an empty string
|
||||||
if ( ( std::string::npos == startpos ) || ( std::string::npos == endpos ) )
|
if ( ( std::string::npos == startpos ) || ( std::string::npos == endpos ) )
|
||||||
{
|
|
||||||
return std::string("");
|
return std::string("");
|
||||||
}
|
|
||||||
else
|
|
||||||
return str.substr(startpos, endpos-startpos+1);
|
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;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string stringtf( const char *format, ... )
|
const std::string stringtf( const char *format, ... ) {
|
||||||
{
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char tempBuffer[8192];
|
char tempBuffer[8192];
|
||||||
std::string tempString;
|
std::string tempString;
|
||||||
|
@ -79,11 +75,10 @@ const std::string stringtf( const char *format, ... )
|
||||||
|
|
||||||
tempString = tempBuffer;
|
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;
|
va_list ap;
|
||||||
char tempBuffer[8192];
|
char tempBuffer[8192];
|
||||||
std::string tempString;
|
std::string tempString;
|
||||||
|
@ -94,7 +89,7 @@ const std::string stringtf( const std::string format, ... )
|
||||||
|
|
||||||
tempString = tempBuffer;
|
tempString = tempBuffer;
|
||||||
|
|
||||||
return( tempString );
|
return tempString;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool startsWith(const std::string &haystack, const std::string &needle) {
|
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) {
|
const std::string base64Encode(const std::string &inString) {
|
||||||
static char base64_table[64] = { '\0' };
|
static char base64_table[64] = { '\0' };
|
||||||
|
|
||||||
if ( !base64_table[0] )
|
if ( !base64_table[0] ) {
|
||||||
{
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for ( char c = 'A'; c <= 'Z'; c++ )
|
for ( char c = 'A'; c <= 'Z'; c++ )
|
||||||
base64_table[i++] = c;
|
base64_table[i++] = c;
|
||||||
|
@ -162,39 +156,32 @@ const std::string base64Encode(const std::string &inString) {
|
||||||
outString.reserve(2 * inString.size());
|
outString.reserve(2 * inString.size());
|
||||||
|
|
||||||
const char *inPtr = inString.c_str();
|
const char *inPtr = inString.c_str();
|
||||||
while( *inPtr )
|
while ( *inPtr ) {
|
||||||
{
|
|
||||||
unsigned char selection = *inPtr >> 2;
|
unsigned char selection = *inPtr >> 2;
|
||||||
unsigned char remainder = (*inPtr++ & 0x03) << 4;
|
unsigned char remainder = (*inPtr++ & 0x03) << 4;
|
||||||
outString += base64_table[selection];
|
outString += base64_table[selection];
|
||||||
|
|
||||||
if ( *inPtr )
|
if ( *inPtr ) {
|
||||||
{
|
|
||||||
selection = remainder | (*inPtr >> 4);
|
selection = remainder | (*inPtr >> 4);
|
||||||
remainder = (*inPtr++ & 0x0f) << 2;
|
remainder = (*inPtr++ & 0x0f) << 2;
|
||||||
outString += base64_table[selection];
|
outString += base64_table[selection];
|
||||||
|
|
||||||
if ( *inPtr )
|
if ( *inPtr ) {
|
||||||
{
|
|
||||||
selection = remainder | (*inPtr >> 6);
|
selection = remainder | (*inPtr >> 6);
|
||||||
outString += base64_table[selection];
|
outString += base64_table[selection];
|
||||||
selection = (*inPtr++ & 0x3f);
|
selection = (*inPtr++ & 0x3f);
|
||||||
outString += base64_table[selection];
|
outString += base64_table[selection];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
outString += base64_table[remainder];
|
outString += base64_table[remainder];
|
||||||
outString += '=';
|
outString += '=';
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
outString += base64_table[remainder];
|
outString += base64_table[remainder];
|
||||||
outString += '=';
|
outString += '=';
|
||||||
outString += '=';
|
outString += '=';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return( outString );
|
return outString;
|
||||||
}
|
}
|
||||||
|
|
||||||
int split(const char* string, const char delim, std::vector<std::string>& items) {
|
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 */
|
/* Detect special hardware features, such as SIMD instruction sets */
|
||||||
void hwcaps_detect() {
|
void hwcaps_detect() {
|
||||||
neonversion = 0;
|
neonversion = 0;
|
||||||
sseversion = 0;
|
sse_version = 0;
|
||||||
#if (defined(__i386__) || defined(__x86_64__))
|
#if (defined(__i386__) || defined(__x86_64__))
|
||||||
/* x86 or x86-64 processor */
|
/* x86 or x86-64 processor */
|
||||||
uint32_t r_edx, r_ecx, r_ebx;
|
uint32_t r_edx, r_ecx, r_ebx;
|
||||||
|
@ -278,31 +265,31 @@ void hwcaps_detect() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( r_ebx & 0x00000020 ) {
|
if ( r_ebx & 0x00000020 ) {
|
||||||
sseversion = 52; /* AVX2 */
|
sse_version = 52; /* AVX2 */
|
||||||
Debug(1, "Detected a x86\\x86-64 processor with AVX2");
|
Debug(1, "Detected a x86\\x86-64 processor with AVX2");
|
||||||
} else if ( r_ecx & 0x10000000 ) {
|
} else if ( r_ecx & 0x10000000 ) {
|
||||||
sseversion = 51; /* AVX */
|
sse_version = 51; /* AVX */
|
||||||
Debug(1, "Detected a x86\\x86-64 processor with AVX");
|
Debug(1, "Detected a x86\\x86-64 processor with AVX");
|
||||||
} else if ( r_ecx & 0x00100000 ) {
|
} 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");
|
Debug(1, "Detected a x86\\x86-64 processor with SSE4.2");
|
||||||
} else if ( r_ecx & 0x00080000 ) {
|
} 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");
|
Debug(1, "Detected a x86\\x86-64 processor with SSE4.1");
|
||||||
} else if ( r_ecx & 0x00000200 ) {
|
} else if ( r_ecx & 0x00000200 ) {
|
||||||
sseversion = 35; /* SSSE3 */
|
sse_version = 35; /* SSSE3 */
|
||||||
Debug(1,"Detected a x86\\x86-64 processor with SSSE3");
|
Debug(1,"Detected a x86\\x86-64 processor with SSSE3");
|
||||||
} else if ( r_ecx & 0x00000001 ) {
|
} else if ( r_ecx & 0x00000001 ) {
|
||||||
sseversion = 30; /* SSE3 */
|
sse_version = 30; /* SSE3 */
|
||||||
Debug(1, "Detected a x86\\x86-64 processor with SSE3");
|
Debug(1, "Detected a x86\\x86-64 processor with SSE3");
|
||||||
} else if ( r_edx & 0x04000000 ) {
|
} else if ( r_edx & 0x04000000 ) {
|
||||||
sseversion = 20; /* SSE2 */
|
sse_version = 20; /* SSE2 */
|
||||||
Debug(1, "Detected a x86\\x86-64 processor with SSE2");
|
Debug(1, "Detected a x86\\x86-64 processor with SSE2");
|
||||||
} else if ( r_edx & 0x02000000 ) {
|
} else if ( r_edx & 0x02000000 ) {
|
||||||
sseversion = 10; /* SSE */
|
sse_version = 10; /* SSE */
|
||||||
Debug(1, "Detected a x86\\x86-64 processor with SSE");
|
Debug(1, "Detected a x86\\x86-64 processor with SSE");
|
||||||
} else {
|
} else {
|
||||||
sseversion = 0;
|
sse_version = 0;
|
||||||
Debug(1, "Detected a x86\\x86-64 processor");
|
Debug(1, "Detected a x86\\x86-64 processor");
|
||||||
}
|
}
|
||||||
#elif defined(__arm__)
|
#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 timespec_diff(struct timespec *start, struct timespec *end, struct timespec *diff);
|
||||||
|
|
||||||
void hwcaps_detect();
|
void hwcaps_detect();
|
||||||
extern unsigned int sseversion;
|
extern unsigned int sse_version;
|
||||||
extern unsigned int neonversion;
|
extern unsigned int neonversion;
|
||||||
|
|
||||||
char *timeval_to_string( struct timeval tv );
|
char *timeval_to_string( struct timeval tv );
|
||||||
|
|
|
@ -37,11 +37,12 @@ VideoStore::VideoStore(
|
||||||
const char *format_in,
|
const char *format_in,
|
||||||
AVStream *p_video_in_stream,
|
AVStream *p_video_in_stream,
|
||||||
AVStream *p_audio_in_stream,
|
AVStream *p_audio_in_stream,
|
||||||
Monitor *monitor
|
Monitor *p_monitor
|
||||||
) {
|
) {
|
||||||
|
|
||||||
video_in_stream = p_video_in_stream;
|
video_in_stream = p_video_in_stream;
|
||||||
audio_in_stream = p_audio_in_stream;
|
audio_in_stream = p_audio_in_stream;
|
||||||
|
monitor = p_monitor;
|
||||||
|
|
||||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||||
//video_in_ctx = avcodec_alloc_context3(NULL);
|
//video_in_ctx = avcodec_alloc_context3(NULL);
|
||||||
|
@ -213,11 +214,18 @@ VideoStore::VideoStore(
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
|
#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
|
/* 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
|
* * think what I was trying to achieve here was to have zm_dump_codecpar output nice info
|
||||||
* */
|
* */
|
||||||
#if 0
|
|
||||||
AVDictionary *opts = 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 ) {
|
if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) {
|
||||||
Warning("Can't open video codec (%s) %s",
|
Warning("Can't open video codec (%s) %s",
|
||||||
video_out_codec->name,
|
video_out_codec->name,
|
||||||
|
@ -407,18 +415,36 @@ bool VideoStore::open() {
|
||||||
if ( audio_out_stream ) zm_dump_stream_format(oc, 1, 0, 1);
|
if ( audio_out_stream ) zm_dump_stream_format(oc, 1, 0, 1);
|
||||||
|
|
||||||
AVDictionary *opts = NULL;
|
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);
|
// av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
|
||||||
// Shiboleth reports that this may break seeking in mp4 before it downloads
|
// 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", 0);
|
||||||
// av_dict_set(&opts, "movflags",
|
// av_dict_set(&opts, "movflags",
|
||||||
// "frag_keyframe+empty_moov+default_base_moof", 0);
|
// "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 ) {
|
||||||
// if ((ret = avformat_write_header(oc, &opts)) < 0) {
|
Warning("Unable to set movflags trying with defaults.");
|
||||||
Warning("Unable to set movflags to frag_custom+dash+delay_moov");
|
|
||||||
/* Write the stream header, if any. */
|
|
||||||
ret = avformat_write_header(oc, NULL);
|
ret = avformat_write_header(oc, NULL);
|
||||||
} else if ( av_dict_count(opts) != 0 ) {
|
} 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 ( opts ) av_dict_free(&opts);
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
|
|
|
@ -19,7 +19,6 @@ extern "C" {
|
||||||
|
|
||||||
class VideoStore {
|
class VideoStore {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
AVOutputFormat *out_format;
|
AVOutputFormat *out_format;
|
||||||
AVFormatContext *oc;
|
AVFormatContext *oc;
|
||||||
|
|
||||||
|
@ -30,6 +29,7 @@ private:
|
||||||
AVStream *video_in_stream;
|
AVStream *video_in_stream;
|
||||||
|
|
||||||
AVStream *audio_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
|
// Move this into the object so that we aren't constantly allocating/deallocating it on the stack
|
||||||
AVPacket opkt;
|
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);
|
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);
|
sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
|
||||||
} else {
|
} else {
|
||||||
std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
|
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");
|
Debug(1, "Failed to prime capture of initial monitor");
|
||||||
}
|
}
|
||||||
prime_capture_log_count ++;
|
prime_capture_log_count ++;
|
||||||
|
if ( !zm_terminate )
|
||||||
sleep(10);
|
sleep(10);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ fi;
|
||||||
|
|
||||||
if [ "$DISTROS" == "" ]; then
|
if [ "$DISTROS" == "" ]; then
|
||||||
if [ "$RELEASE" != "" ]; then
|
if [ "$RELEASE" != "" ]; then
|
||||||
DISTROS="xenial,bionic,disco,eoan,focal,trusty"
|
DISTROS="xenial,bionic,focal,trusty"
|
||||||
else
|
else
|
||||||
DISTROS=`lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`;
|
DISTROS=`lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`;
|
||||||
fi;
|
fi;
|
||||||
|
@ -220,15 +220,20 @@ IFS=',' ;for DISTRO in `echo "$DISTROS"`; do
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
# Generate Changlog
|
# Generate Changlog
|
||||||
if [ "$DISTRO" == "trusty" ] || [ "$DISTRO" == "precise" ]; then
|
if [ "$DISTRO" == "trusty" ] || [ "$DISTRO" == "precise" ]
|
||||||
|
then
|
||||||
cp -Rpd distros/ubuntu1204 debian
|
cp -Rpd distros/ubuntu1204 debian
|
||||||
else
|
|
||||||
if [ "$DISTRO" == "wheezy" ]; then
|
elif [ "$DISTRO" == "wheezy" ]
|
||||||
|
then
|
||||||
cp -Rpd distros/debian debian
|
cp -Rpd distros/debian debian
|
||||||
|
|
||||||
|
elif [ "$DISTRO" == "beowulf" ]
|
||||||
|
then
|
||||||
|
cp -Rpd distros/beowulf debian
|
||||||
else
|
else
|
||||||
cp -Rpd distros/ubuntu1604 debian
|
cp -Rpd distros/ubuntu1604 debian
|
||||||
fi;
|
fi;
|
||||||
fi;
|
|
||||||
|
|
||||||
if [ "$DEBEMAIL" != "" ] && [ "$DEBFULLNAME" != "" ]; then
|
if [ "$DEBEMAIL" != "" ] && [ "$DEBFULLNAME" != "" ]; then
|
||||||
AUTHOR="$DEBFULLNAME <$DEBEMAIL>"
|
AUTHOR="$DEBFULLNAME <$DEBEMAIL>"
|
||||||
|
|
|
@ -37,7 +37,7 @@ echo "Target subfolder set to $targetfolder"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
echo "Running \$(rsync -v -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1)"
|
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
|
if [ "$?" -eq 0 ]; then
|
||||||
echo
|
echo
|
||||||
echo "Files copied successfully."
|
echo "Files copied successfully."
|
||||||
|
|
|
@ -19,7 +19,7 @@ $statusData = array(
|
||||||
'limit' => 1,
|
'limit' => 1,
|
||||||
'elements' => array(
|
'elements' => array(
|
||||||
'MonitorCount' => array( 'sql' => 'count(*)' ),
|
'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') ),
|
'State' => array( 'func' => 'daemonCheck()?'.translate('Running').':'.translate('Stopped') ),
|
||||||
'Load' => array( 'func' => 'getLoad()' ),
|
'Load' => array( 'func' => 'getLoad()' ),
|
||||||
'Disk' => array( 'func' => 'getDiskPercent()' ),
|
'Disk' => array( 'func' => 'getDiskPercent()' ),
|
||||||
|
@ -246,7 +246,7 @@ function collectData() {
|
||||||
if ( isset($elementData['sql']) )
|
if ( isset($elementData['sql']) )
|
||||||
$fieldSql[] = $elementData['sql'].' as '.$element;
|
$fieldSql[] = $elementData['sql'].' as '.$element;
|
||||||
else
|
else
|
||||||
$fieldSql[] = $element;
|
$fieldSql[] = '`'.$element.'`';
|
||||||
if ( isset($elementData['table']) && isset($elementData['join']) ) {
|
if ( isset($elementData['table']) && isset($elementData['join']) ) {
|
||||||
$joinSql[] = 'left join '.$elementData['table'].' on '.$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);
|
preg_match('/^(\w+)\s*(ASC|DESC)?( NULLS FIRST)?$/i', $sort_field, $matches);
|
||||||
if ( count($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];
|
$sql .= $matches[1];
|
||||||
} else {
|
} else {
|
||||||
ZM\Error('Sort field ' . $matches[1] . ' not in SQL Fields');
|
ZM\Error('Sort field ' . $matches[1] . ' not in SQL Fields');
|
||||||
|
@ -296,7 +296,7 @@ function collectData() {
|
||||||
$sql .= ' '.strtoupper($matches[3]);
|
$sql .= ' '.strtoupper($matches[3]);
|
||||||
}
|
}
|
||||||
} else {
|
} 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 foreach sort field
|
||||||
} # end if has sort
|
} # end if has sort
|
||||||
|
|
|
@ -128,27 +128,3 @@ global $configvals;
|
||||||
foreach( $configvals as $key => $value) {
|
foreach( $configvals as $key => $value) {
|
||||||
Configure::write($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.
|
// Find the max Frame for this Event. Error out otherwise.
|
||||||
$this->loadModel('Frame');
|
$this->loadModel('Frame');
|
||||||
|
|
||||||
if (! $frame = $this->Frame->find('first', array(
|
$frame = $this->Frame->find('first', array(
|
||||||
'conditions' => array(
|
'conditions' => array(
|
||||||
'EventId' => $event['Event']['Id'],
|
'EventId' => $event['Event']['Id'],
|
||||||
'Score' => $event['Event']['MaxScore']
|
'Score' => $event['Event']['MaxScore']
|
||||||
)
|
)));
|
||||||
))) {
|
return empty($frame)?null:$frame['Frame']['Id'];
|
||||||
throw new NotFoundException(__('Can not find Frame for Event ' . $event['Event']['Id']));
|
|
||||||
}
|
|
||||||
return $frame['Frame']['Id'];
|
|
||||||
}
|
}
|
||||||
} // end class EventsController
|
} // end class EventsController
|
||||||
|
|
|
@ -14,6 +14,18 @@ class UsersController extends AppController {
|
||||||
*/
|
*/
|
||||||
public $components = array('RequestHandler', 'Paginator');
|
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
|
* index method
|
||||||
*
|
*
|
||||||
|
@ -23,6 +35,12 @@ class UsersController extends AppController {
|
||||||
public function index() {
|
public function index() {
|
||||||
$this->User->recursive = 0;
|
$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');
|
$users = $this->Paginator->paginate('User');
|
||||||
|
|
||||||
$this->set(compact('users'));
|
$this->set(compact('users'));
|
||||||
|
@ -36,16 +54,20 @@ class UsersController extends AppController {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function view($id = null) {
|
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;
|
$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) ) {
|
if ( !$this->User->exists($id) ) {
|
||||||
throw new NotFoundException(__('Invalid user'));
|
throw new NotFoundException(__('Invalid user'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$options = array('conditions' => array('User.' . $this->User->primaryKey => $id));
|
$options = array('conditions' => array('User.' . $this->User->primaryKey => $id));
|
||||||
$user = $this->User->find('first', $options);
|
$user = $this->User->find('first', $options);
|
||||||
|
|
||||||
|
@ -62,6 +84,13 @@ class UsersController extends AppController {
|
||||||
*/
|
*/
|
||||||
public function add() {
|
public function add() {
|
||||||
if ( $this->request->is('post') ) {
|
if ( $this->request->is('post') ) {
|
||||||
|
|
||||||
|
global $user;
|
||||||
|
if ( $user['System'] != 'Edit' ) {
|
||||||
|
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->User->create();
|
$this->User->create();
|
||||||
if ( $this->User->save($this->request->data) ) {
|
if ( $this->User->save($this->request->data) ) {
|
||||||
return $this->flash(__('The user has been saved.'), array('action' => 'index'));
|
return $this->flash(__('The user has been saved.'), array('action' => 'index'));
|
||||||
|
@ -82,6 +111,13 @@ class UsersController extends AppController {
|
||||||
public function edit($id = null) {
|
public function edit($id = null) {
|
||||||
$this->User->id = $id;
|
$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) ) {
|
if ( !$this->User->exists($id) ) {
|
||||||
throw new NotFoundException(__('Invalid user'));
|
throw new NotFoundException(__('Invalid user'));
|
||||||
}
|
}
|
||||||
|
@ -93,8 +129,10 @@ class UsersController extends AppController {
|
||||||
$message = 'Error';
|
$message = 'Error';
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
$this->request->data = $this->User->read(null, $id);
|
||||||
unset($this->request->data['User']['password']);
|
unset($this->request->data['User']['Password']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->set(array(
|
$this->set(array(
|
||||||
|
@ -112,6 +150,13 @@ class UsersController extends AppController {
|
||||||
*/
|
*/
|
||||||
public function delete($id = null) {
|
public function delete($id = null) {
|
||||||
$this->User->id = $id;
|
$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() ) {
|
if ( !$this->User->exists() ) {
|
||||||
throw new NotFoundException(__('Invalid user'));
|
throw new NotFoundException(__('Invalid user'));
|
||||||
}
|
}
|
||||||
|
@ -126,47 +171,4 @@ class UsersController extends AppController {
|
||||||
'_serialize' => array('message')
|
'_serialize' => array('message')
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
} # end class UsersController
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ class ZonesController extends AppController {
|
||||||
'_serialize' => array('zones')
|
'_serialize' => array('zones')
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
$this->Zone->recursive = -1;
|
$this->Zone->recursive = -1;
|
||||||
|
|
||||||
|
@ -63,7 +64,11 @@ class ZonesController extends AppController {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function add() {
|
public function add() {
|
||||||
if ( $this->request->is('post') ) {
|
|
||||||
|
if ( !$this->request->is('post') ) {
|
||||||
|
throw new BadRequestException(__('Invalid method. Should be post'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
global $user;
|
global $user;
|
||||||
$canEdit = (!$user) || $user['Monitors'] == 'Edit';
|
$canEdit = (!$user) || $user['Monitors'] == 'Edit';
|
||||||
|
@ -72,14 +77,30 @@ class ZonesController extends AppController {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$zone = null;
|
||||||
|
|
||||||
$this->Zone->create();
|
$this->Zone->create();
|
||||||
if ( $this->Zone->save($this->request->data) ) {
|
$zone = $this->Zone->save($this->request->data);
|
||||||
return $this->flash(__('The zone has been saved.'), array('action' => 'index'));
|
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
|
* edit method
|
||||||
|
|
|
@ -3,8 +3,6 @@ App::uses('AppModel', 'Model');
|
||||||
/**
|
/**
|
||||||
* User Model
|
* User Model
|
||||||
*
|
*
|
||||||
* @property Monitor $Monitor
|
|
||||||
* @property Frame $Frame
|
|
||||||
*/
|
*/
|
||||||
class User extends AppModel {
|
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
|
* Use table
|
||||||
*
|
*
|
||||||
|
@ -53,14 +65,6 @@ class User extends AppModel {
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
public $belongsTo = array(
|
public $belongsTo = array(
|
||||||
/*'Monitor' => array(
|
|
||||||
'className' => 'Monitor',
|
|
||||||
'foreignKey' => 'MonitorId',
|
|
||||||
'conditions' => '',
|
|
||||||
'fields' => '',
|
|
||||||
'order' => ''
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,21 +73,6 @@ class User extends AppModel {
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
public $hasMany = 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;
|
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
|
//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(
|
'Monitor' => array(
|
||||||
'className' => 'Monitor',
|
'className' => 'Monitor',
|
||||||
'foreignKey' => 'MonitorId',
|
'foreignKey' => 'MonitorId',
|
||||||
'conditions' => '',
|
//'conditions' => '',
|
||||||
'fields' => '',
|
//'fields' => '',
|
||||||
'order' => ''
|
//'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;
|
return $streamSrc;
|
||||||
} // end function getStreamSrc
|
} // 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='' ) {
|
function DiskSpace( $new='' ) {
|
||||||
if ( is_null($new) or ( $new != '' ) ) {
|
if ( is_null($new) or ( $new != '' ) ) {
|
||||||
$this->{'DiskSpace'} = $new;
|
$this->{'DiskSpace'} = $new;
|
||||||
}
|
}
|
||||||
if ( (!property_exists($this, 'DiskSpace')) or (null === $this->{'DiskSpace'}) ) {
|
if ( (!property_exists($this, 'DiskSpace')) or (null === $this->{'DiskSpace'}) ) {
|
||||||
$this->{'DiskSpace'} = folder_size($this->Path());
|
$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'}));
|
dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'}));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return $this->{'DiskSpace'};
|
return $this->{'DiskSpace'};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +394,7 @@ class Event extends ZM_Object {
|
||||||
if ( ( !$frame ) and file_exists($eventPath.'/snapshot.jpg') ) {
|
if ( ( !$frame ) and file_exists($eventPath.'/snapshot.jpg') ) {
|
||||||
# No frame specified, so look for a snapshot to use
|
# No frame specified, so look for a snapshot to use
|
||||||
$captImage = 'snapshot.jpg';
|
$captImage = 'snapshot.jpg';
|
||||||
Logger::Debug("Frame not specified, using snapshot");
|
Logger::Debug('Frame not specified, using snapshot');
|
||||||
$frame = array('FrameId'=>'snapshot', 'Type'=>'', 'Delta'=>0);
|
$frame = array('FrameId'=>'snapshot', 'Type'=>'', 'Delta'=>0);
|
||||||
} else {
|
} else {
|
||||||
$captImage = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyze.jpg', $frame['FrameId']);
|
$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();
|
$videoPath = $eventPath.'/'.$Event->DefaultVideo();
|
||||||
|
|
||||||
if ( !file_exists($videoPath) ) {
|
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 '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
#$command ='ffmpeg -v 0 -i '.$videoPath.' -vf "select=gte(n\\,'.$frame['FrameId'].'),setpts=PTS-STARTPTS" '.$eventPath.'/'.$captImage;
|
#$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;
|
$command ='ffmpeg -ss '. $frame['Delta'] .' -i '.$videoPath.' -frames:v 1 '.$eventPath.'/'.$captImage;
|
||||||
Logger::Debug( "Running $command" );
|
Logger::Debug('Running '.$command);
|
||||||
$output = array();
|
$output = array();
|
||||||
$retval = 0;
|
$retval = 0;
|
||||||
exec($command, $output, $retval);
|
exec($command, $output, $retval);
|
||||||
Logger::Debug("Retval: $retval, output: " . implode("\n", $output));
|
Logger::Debug("Retval: $retval, output: " . implode("\n", $output));
|
||||||
} else {
|
} 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 capture file exists
|
||||||
} // end if analyze file exists
|
} // end if analyze file exists
|
||||||
|
@ -421,7 +426,7 @@ class Event extends ZM_Object {
|
||||||
|
|
||||||
$captPath = $eventPath.'/'.$captImage;
|
$captPath = $eventPath.'/'.$captImage;
|
||||||
if ( !file_exists($captPath) ) {
|
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']);
|
$analImage = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyse.jpg', $frame['FrameId']);
|
||||||
|
@ -484,7 +489,7 @@ class Event extends ZM_Object {
|
||||||
);
|
);
|
||||||
|
|
||||||
return $imageData;
|
return $imageData;
|
||||||
}
|
} # getImageSrc
|
||||||
|
|
||||||
public function link_to($text=null) {
|
public function link_to($text=null) {
|
||||||
if ( !$text )
|
if ( !$text )
|
||||||
|
|
|
@ -19,9 +19,9 @@ class Group extends ZM_Object {
|
||||||
|
|
||||||
public function delete() {
|
public function delete() {
|
||||||
if ( property_exists($this, 'Id') ) {
|
if ( property_exists($this, 'Id') ) {
|
||||||
dbQuery('DELETE FROM Groups_Monitors WHERE GroupId=?', 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('UPDATE `Groups` SET `ParentId`=NULL WHERE `ParentId`=?', array($this->{'Id'}));
|
||||||
dbQuery('DELETE FROM Groups WHERE Id=?', array($this->{'Id'}));
|
dbQuery('DELETE FROM `Groups` WHERE Id=?', array($this->{'Id'}));
|
||||||
if ( isset($_COOKIE['zmGroup']) ) {
|
if ( isset($_COOKIE['zmGroup']) ) {
|
||||||
if ( $this->{'Id'} == $_COOKIE['zmGroup'] ) {
|
if ( $this->{'Id'} == $_COOKIE['zmGroup'] ) {
|
||||||
unset($_COOKIE['zmGroup']);
|
unset($_COOKIE['zmGroup']);
|
||||||
|
@ -47,7 +47,7 @@ class Group extends ZM_Object {
|
||||||
|
|
||||||
public function MonitorIds( ) {
|
public function MonitorIds( ) {
|
||||||
if ( ! property_exists($this, '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'};
|
return $this->{'MonitorIds'};
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,6 +201,11 @@ class Monitor extends ZM_Object {
|
||||||
if ( ZM_RAND_STREAM ) {
|
if ( ZM_RAND_STREAM ) {
|
||||||
$args['rand'] = time();
|
$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);
|
$streamSrc .= '?'.http_build_query($args, '', $querySep);
|
||||||
|
|
||||||
|
@ -293,7 +298,7 @@ class Monitor extends ZM_Object {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Logger::Debug("sending command to $url");
|
Logger::Debug('sending command to '.$url);
|
||||||
|
|
||||||
$context = stream_context_create();
|
$context = stream_context_create();
|
||||||
try {
|
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 ( (!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 ( $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', 'zmtrack.pl', '-m '.$this->{'Id'});
|
||||||
}
|
}
|
||||||
daemonControl('stop', 'zma', '-m '.$this->{'Id'});
|
daemonControl('stop', 'zma', '-m '.$this->{'Id'});
|
||||||
|
@ -340,7 +346,7 @@ class Monitor extends ZM_Object {
|
||||||
} else if ( $this->ServerId() ) {
|
} else if ( $this->ServerId() ) {
|
||||||
$Server = $this->Server();
|
$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_OPT_USE_AUTH ) {
|
||||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||||
|
@ -490,12 +496,11 @@ class Monitor extends ZM_Object {
|
||||||
foreach ( explode(' ', $command) as $option ) {
|
foreach ( explode(' ', $command) as $option ) {
|
||||||
if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
|
if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
|
||||||
$options[$matches[1]] = $matches[2]?$matches[2]:1;
|
$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");
|
Warning("Ignored command for zmcontrol $option in $command");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( !count($options) ) {
|
if ( !count($options) ) {
|
||||||
|
|
||||||
if ( $command == 'quit' or $command == 'start' or $command == 'stop' ) {
|
if ( $command == 'quit' or $command == 'start' or $command == 'stop' ) {
|
||||||
# These are special as we now run zmcontrol as a daemon through zmdc.
|
# These are special as we now run zmcontrol as a daemon through zmdc.
|
||||||
$status = daemonStatus('zmcontrol.pl', array('--id', $this->{'Id'}));
|
$status = daemonStatus('zmcontrol.pl', array('--id', $this->{'Id'}));
|
||||||
|
@ -539,7 +544,7 @@ class Monitor extends ZM_Object {
|
||||||
} else if ( $this->ServerId() ) {
|
} else if ( $this->ServerId() ) {
|
||||||
$Server = $this->Server();
|
$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_OPT_USE_AUTH ) {
|
||||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||||
|
|
|
@ -306,7 +306,7 @@ class ZM_Object {
|
||||||
$fields = array_keys($fields);
|
$fields = array_keys($fields);
|
||||||
|
|
||||||
if ( $this->Id() ) {
|
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 = array_map(function($field){ return $this->{$field};}, $fields);
|
||||||
$values[] = $this->{'Id'};
|
$values[] = $this->{'Id'};
|
||||||
if ( dbQuery($sql, $values) )
|
if ( dbQuery($sql, $values) )
|
||||||
|
@ -314,8 +314,8 @@ class ZM_Object {
|
||||||
} else {
|
} else {
|
||||||
unset($fields['Id']);
|
unset($fields['Id']);
|
||||||
|
|
||||||
$sql = 'INSERT INTO '.$table.
|
$sql = 'INSERT INTO `'.$table.
|
||||||
' ('.implode(', ', array_map(function($field) {return '`'.$field.'`';}, $fields)).
|
'` ('.implode(', ', array_map(function($field) {return '`'.$field.'`';}, $fields)).
|
||||||
') VALUES ('.
|
') VALUES ('.
|
||||||
implode(', ', array_map(function($field){return '?';}, $fields)).')';
|
implode(', ', array_map(function($field){return '?';}, $fields)).')';
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ class ZM_Object {
|
||||||
public function delete() {
|
public function delete() {
|
||||||
$class = get_class($this);
|
$class = get_class($this);
|
||||||
$table = $class::$table;
|
$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'}]) )
|
if ( isset($object_cache[$class]) and isset($object_cache[$class][$this->{'Id'}]) )
|
||||||
unset($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
|
// We update the request id so that the newly saved filter is auto-selected
|
||||||
$_REQUEST['Id'] = $filter->Id();
|
$_REQUEST['Id'] = $filter->Id();
|
||||||
}
|
}
|
||||||
if ( $filter->Background() )
|
|
||||||
$filter->control('start');
|
|
||||||
|
|
||||||
if ( $action == 'execute' ) {
|
if ( $action == 'execute' ) {
|
||||||
$filter->execute();
|
$filter->execute();
|
||||||
|
@ -94,6 +92,8 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
|
||||||
$filter->delete();
|
$filter->delete();
|
||||||
|
|
||||||
$view = 'events';
|
$view = 'events';
|
||||||
|
} else if ( $filter->Background() ) {
|
||||||
|
$filter->control('start');
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ( $action == 'control' ) {
|
} else if ( $action == 'control' ) {
|
||||||
|
|
|
@ -18,16 +18,24 @@
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
//
|
//
|
||||||
|
|
||||||
if ( $action == 'user' ) {
|
if ( $action == 'Save' ) {
|
||||||
if ( canEdit('System') ) {
|
if ( canEdit('System') ) {
|
||||||
if ( !empty($_REQUEST['uid']) )
|
if ( !empty($_REQUEST['uid']) ) {
|
||||||
$dbUser = dbFetchOne('SELECT * FROM Users WHERE Id=?', NULL, array($_REQUEST['uid']));
|
$dbUser = dbFetchOne('SELECT * FROM Users WHERE Id=?', NULL, array($_REQUEST['uid']));
|
||||||
else
|
} else {
|
||||||
$dbUser = array();
|
$dbUser = array();
|
||||||
|
}
|
||||||
|
|
||||||
$types = 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);
|
$changes = getFormChanges($dbUser, $_REQUEST['newUser'], $types);
|
||||||
|
|
||||||
|
|
||||||
|
if ( isset($_REQUEST['newUser']['Password']) ) {
|
||||||
if ( function_exists('password_hash') ) {
|
if ( function_exists('password_hash') ) {
|
||||||
$pass_hash = '"'.password_hash($_REQUEST['newUser']['Password'], PASSWORD_BCRYPT).'"';
|
$pass_hash = '"'.password_hash($_REQUEST['newUser']['Password'], PASSWORD_BCRYPT).'"';
|
||||||
} else {
|
} else {
|
||||||
|
@ -40,6 +48,7 @@ if ( $action == 'user' ) {
|
||||||
} else {
|
} else {
|
||||||
unset($changes['Password']);
|
unset($changes['Password']);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( count($changes) ) {
|
if ( count($changes) ) {
|
||||||
if ( !empty($_REQUEST['uid']) ) {
|
if ( !empty($_REQUEST['uid']) ) {
|
||||||
|
|
|
@ -260,6 +260,22 @@ function userFromSession() {
|
||||||
return $user;
|
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 ( ZM_OPT_USE_AUTH ) {
|
||||||
if ( !empty($_REQUEST['token']) ) {
|
if ( !empty($_REQUEST['token']) ) {
|
||||||
// we only need to get the username here
|
// we only need to get the username here
|
||||||
|
|
|
@ -389,7 +389,7 @@ function csrf_conf($key, $val) {
|
||||||
*/
|
*/
|
||||||
function csrf_start() {
|
function csrf_start() {
|
||||||
if ($GLOBALS['csrf']['auto-session'] && !session_id()) {
|
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['dbLogLevel'] = DB_LOG_OFF;
|
||||||
|
|
||||||
$GLOBALS['dbConn'] = false;
|
$GLOBALS['dbConn'] = false;
|
||||||
|
require_once('logger.php');
|
||||||
|
|
||||||
function dbConnect() {
|
function dbConnect() {
|
||||||
global $dbConn;
|
global $dbConn;
|
||||||
|
|
||||||
|
$socket = '';
|
||||||
|
if ( ZM_DB_HOST ) {
|
||||||
if ( strpos(ZM_DB_HOST, ':') ) {
|
if ( strpos(ZM_DB_HOST, ':') ) {
|
||||||
// Host variable may carry a port or socket.
|
// Host variable may carry a port or socket.
|
||||||
list($host, $portOrSocket) = explode(':', ZM_DB_HOST, 2);
|
list($host, $portOrSocket) = explode(':', ZM_DB_HOST, 2);
|
||||||
if ( ctype_digit($portOrSocket) ) {
|
if ( ctype_digit($portOrSocket) ) {
|
||||||
$socket = ':host='.$host . ';port='.$portOrSocket;
|
$socket = ':host='.$host . ';port='.$portOrSocket.';';
|
||||||
} else {
|
} else {
|
||||||
$socket = ':unix_socket='.$portOrSocket;
|
$socket = ':unix_socket='.$portOrSocket.';';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$socket = ':host='.ZM_DB_HOST;
|
$socket = ':host='.ZM_DB_HOST.';';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$socket = ':host=localhost;';
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -49,9 +55,9 @@ function dbConnect() {
|
||||||
PDO::MYSQL_ATTR_SSL_KEY => ZM_DB_SSL_CLIENT_KEY,
|
PDO::MYSQL_ATTR_SSL_KEY => ZM_DB_SSL_CLIENT_KEY,
|
||||||
PDO::MYSQL_ATTR_SSL_CERT => ZM_DB_SSL_CLIENT_CERT,
|
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 {
|
} 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);
|
$dbConn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||||
|
@ -61,9 +67,12 @@ function dbConnect() {
|
||||||
error_log('Unable to connect to ZM DB ' . $ex->getMessage());
|
error_log('Unable to connect to ZM DB ' . $ex->getMessage());
|
||||||
$dbConn = null;
|
$dbConn = null;
|
||||||
}
|
}
|
||||||
}
|
return $dbConn;
|
||||||
|
} // end function dbConnect
|
||||||
|
|
||||||
dbConnect();
|
if ( !dbConnect() ) {
|
||||||
|
ZM\Fatal("Failed db connection to $socket");
|
||||||
|
}
|
||||||
|
|
||||||
function dbDisconnect() {
|
function dbDisconnect() {
|
||||||
global $dbConn;
|
global $dbConn;
|
||||||
|
|
|
@ -40,7 +40,7 @@ function CSPHeaders($view, $nonce) {
|
||||||
if ( ! $Servers )
|
if ( ! $Servers )
|
||||||
$Servers = ZM\Server::find();
|
$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) {
|
switch ($view) {
|
||||||
case 'login': {
|
case 'login': {
|
||||||
if (defined('ZM_OPT_USE_GOOG_RECAPTCHA')
|
if (defined('ZM_OPT_USE_GOOG_RECAPTCHA')
|
||||||
|
@ -840,8 +840,14 @@ function daemonStatus($daemon, $args=false) {
|
||||||
initDaemonStatus();
|
initDaemonStatus();
|
||||||
|
|
||||||
$string = $daemon;
|
$string = $daemon;
|
||||||
if ( $args )
|
if ( $args ) {
|
||||||
|
if ( is_array($args) ) {
|
||||||
|
$string .= join(' ', $args);
|
||||||
|
ZM\Warning("daemonStatus args: $string");
|
||||||
|
} else {
|
||||||
$string .= ' ' . $args;
|
$string .= ' ' . $args;
|
||||||
|
}
|
||||||
|
}
|
||||||
return ( strpos($daemon_status, "'$string' running") !== false );
|
return ( strpos($daemon_status, "'$string' running") !== false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1484,15 +1490,15 @@ function getLoad() {
|
||||||
function getDiskPercent($path = ZM_DIR_EVENTS) {
|
function getDiskPercent($path = ZM_DIR_EVENTS) {
|
||||||
$total = disk_total_space($path);
|
$total = disk_total_space($path);
|
||||||
if ( $total === false ) {
|
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;
|
return 0;
|
||||||
} elseif ( $total == 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;
|
return 100;
|
||||||
}
|
}
|
||||||
$free = disk_free_space($path);
|
$free = disk_free_space($path);
|
||||||
if ( $free === false ) {
|
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);
|
$space = round((($total - $free) / $total) * 100);
|
||||||
return $space;
|
return $space;
|
||||||
|
@ -2048,7 +2054,7 @@ function logState() {
|
||||||
if ( $count['Level'] <= ZM\Logger::PANIC )
|
if ( $count['Level'] <= ZM\Logger::PANIC )
|
||||||
$count['Level'] = ZM\Logger::FATAL;
|
$count['Level'] = ZM\Logger::FATAL;
|
||||||
if ( !($levelCount = $levelCounts[$count['Level']]) ) {
|
if ( !($levelCount = $levelCounts[$count['Level']]) ) {
|
||||||
Error('Unexpected Log level '.$count['Level']);
|
ZM\Error('Unexpected Log level '.$count['Level']);
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if ( $levelCount[1] && $count['LevelCount'] >= $levelCount[1] ) {
|
if ( $levelCount[1] && $count['LevelCount'] >= $levelCount[1] ) {
|
||||||
|
@ -2078,15 +2084,20 @@ function checkJsonError($value) {
|
||||||
$value = var_export($value, true);
|
$value = var_export($value, true);
|
||||||
switch ( json_last_error() ) {
|
switch ( json_last_error() ) {
|
||||||
case JSON_ERROR_DEPTH :
|
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 :
|
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 :
|
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 :
|
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 :
|
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:
|
case JSON_ERROR_NONE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2290,7 +2301,8 @@ function validHtmlStr($input) {
|
||||||
function getStreamHTML($monitor, $options = array()) {
|
function getStreamHTML($monitor, $options = array()) {
|
||||||
|
|
||||||
if ( isset($options['scale']) ) {
|
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['width'] = reScale($monitor->ViewWidth(), $options['scale']).'px';
|
||||||
$options['height'] = reScale($monitor->ViewHeight(), $options['scale']).'px';
|
$options['height'] = reScale($monitor->ViewHeight(), $options['scale']).'px';
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -87,6 +87,7 @@ $SLANG = array(
|
||||||
'Actual' => 'Actual',
|
'Actual' => 'Actual',
|
||||||
'AddNewControl' => 'Add New Control',
|
'AddNewControl' => 'Add New Control',
|
||||||
'AddNewMonitor' => 'Add',
|
'AddNewMonitor' => 'Add',
|
||||||
|
'AddMonitorDisabled' => 'Your user is not allowed to add a new monitor',
|
||||||
'AddNewServer' => 'Add New Server',
|
'AddNewServer' => 'Add New Server',
|
||||||
'AddNewStorage' => 'Add New Storage',
|
'AddNewStorage' => 'Add New Storage',
|
||||||
'AddNewUser' => 'Add New User',
|
'AddNewUser' => 'Add New User',
|
||||||
|
@ -983,6 +984,18 @@ $OLANG = array(
|
||||||
"loglevel=debug" Set verbosity of FFmpeg (quiet, panic, fatal, error, warning, info, verbose, debug)
|
"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(
|
'OPTIONS_DECODERHWACCELNAME' => array(
|
||||||
'Help' => '
|
'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.'
|
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 {
|
#content {
|
||||||
width: 96%;
|
width: 100%;
|
||||||
margin: 0 auto 8px auto;
|
margin: 0 auto 8px auto;
|
||||||
line-height: 130%;
|
line-height: 130%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
@ -11,10 +11,30 @@
|
||||||
|
|
||||||
textarea,
|
textarea,
|
||||||
input[name="newMonitor[Name]"],
|
input[name="newMonitor[Name]"],
|
||||||
|
input[name="newMonitor[LabelFormat]"],
|
||||||
input[name="newMonitor[ControlDevice]"],
|
input[name="newMonitor[ControlDevice]"],
|
||||||
input[name="newMonitor[ControlAddress]"] {
|
input[name="newMonitor[ControlAddress]"] {
|
||||||
width: 100%;
|
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[Width]"],
|
||||||
input[name="newMonitor[Height]"] {
|
input[name="newMonitor[Height]"] {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue