Merge branch 'master' of github.com:ZoneMinder/zoneminder
commit
0b0df96271
|
@ -122,13 +122,10 @@ src/libzm.a
|
|||
src/nph-zms
|
||||
src/zm_config_data.h
|
||||
src/zm_config_defines.h
|
||||
src/zma
|
||||
src/zmc
|
||||
src/zmf
|
||||
src/zms
|
||||
src/zmu
|
||||
src/zoneminder-zma.8
|
||||
src/zoneminder-zma.8.gz
|
||||
src/zoneminder-zmc.8
|
||||
src/zoneminder-zmc.8.gz
|
||||
src/zoneminder-zmf.8
|
||||
|
|
|
@ -93,6 +93,11 @@ mark_as_advanced(
|
|||
option(BUILD_TEST_SUITE "Build the test suite" 0)
|
||||
option(BUILD_MAN "Build man pages" 1)
|
||||
option(ASAN "DEBUGGING: Build with AddressSanitizer (ASan) support" 0)
|
||||
option(TSAN "DEBUGGING: Build with ThreadSanitizer (TSan) support" 0)
|
||||
|
||||
if(ASAN AND TSAN)
|
||||
message(FATAL_ERROR "ASAN and TSAN options are mutually exclusive")
|
||||
endif()
|
||||
|
||||
set(ZM_RUNDIR "/var/run/zm" CACHE PATH
|
||||
"Location of transient process files, default: /var/run/zm")
|
||||
|
|
|
@ -19,3 +19,15 @@ if(ASAN)
|
|||
|
||||
message(STATUS "Clang: Enabled AddressSanitizer (ASan)")
|
||||
endif()
|
||||
|
||||
if(TSAN)
|
||||
target_compile_options(zm-compile-option-interface
|
||||
INTERFACE
|
||||
-fsanitize=thread)
|
||||
|
||||
target_link_options(zm-compile-option-interface
|
||||
INTERFACE
|
||||
-fsanitize=thread)
|
||||
|
||||
message(STATUS "Clang: Enabled ThreadSanitizer (TSan)")
|
||||
endif()
|
||||
|
|
|
@ -19,3 +19,15 @@ if(ASAN)
|
|||
|
||||
message(STATUS "GCC: Enabled AddressSanitizer (ASan)")
|
||||
endif()
|
||||
|
||||
if(TSAN)
|
||||
target_compile_options(zm-compile-option-interface
|
||||
INTERFACE
|
||||
-fsanitize=thread)
|
||||
|
||||
target_link_options(zm-compile-option-interface
|
||||
INTERFACE
|
||||
-fsanitize=thread)
|
||||
|
||||
message(STATUS "GCC: Enabled ThreadSanitizer (TSan)")
|
||||
endif()
|
||||
|
|
|
@ -341,7 +341,6 @@ ln -sf %{_sysconfdir}/zm/www/zoneminder.nginx.conf %{_sysconfdir}/zm/www/zonemin
|
|||
%{_datadir}/polkit-1/actions/com.zoneminder.systemctl.policy
|
||||
%{_bindir}/zmsystemctl.pl
|
||||
|
||||
%{_bindir}/zma
|
||||
%{_bindir}/zmaudit.pl
|
||||
%{_bindir}/zmc
|
||||
%{_bindir}/zmcontrol.pl
|
||||
|
|
|
@ -1 +1 @@
|
|||
9
|
||||
12
|
||||
|
|
|
@ -16,11 +16,6 @@ Alias /zm/cache /var/cache/zoneminder/cache
|
|||
# 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
|
||||
|
|
|
@ -2,8 +2,7 @@ Source: zoneminder
|
|||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Isaac Connor <isaac@zoneminder.com>
|
||||
Uploaders: Isaac Connor <isaac@zoneminder.com>
|
||||
Build-Depends: debhelper, dh-systemd, sphinx-doc, python3-sphinx, dh-linktree, dh-systemd, dh-apache2
|
||||
Build-Depends: debhelper (>= 12), sphinx-doc, python3-sphinx, dh-linktree, dh-apache2
|
||||
,cmake
|
||||
,libavdevice-dev
|
||||
,libavcodec-dev
|
||||
|
@ -33,10 +32,8 @@ Build-Depends: debhelper, dh-systemd, sphinx-doc, python3-sphinx, dh-linktree, d
|
|||
,libcrypt-eksblowfish-perl
|
||||
,libdata-entropy-perl
|
||||
,libvncserver-dev
|
||||
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
|
||||
Standards-Version: 4.5.0
|
||||
Homepage: https://www.zoneminder.com/
|
||||
|
||||
Package: zoneminder
|
||||
Architecture: any
|
||||
|
@ -68,8 +65,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,libdata-uuid-perl
|
||||
,libnumber-bytes-human-perl
|
||||
,libfile-slurp-perl
|
||||
,mysql-client | mariadb-client | virtual-mysql-client
|
||||
,perl-modules
|
||||
,default-mysql-client | mariadb-client | virtual-mysql-client
|
||||
,php-mysql, php-gd, php-apcu, php-apc | php-apcu-bc, php-json
|
||||
,policykit-1
|
||||
,rsyslog | system-log-daemon
|
||||
|
@ -80,9 +76,8 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,libvncclient1|libvncclient0
|
||||
Recommends: ${misc:Recommends}
|
||||
,libapache2-mod-php | php-fpm
|
||||
,mysql-server | mariadb-server | virtual-mysql-server
|
||||
,default-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
|
||||
|
@ -146,7 +141,7 @@ Description: ZoneMinder documentation
|
|||
|
||||
Package: zoneminder-dbg
|
||||
Section: debug
|
||||
Priority: extra
|
||||
Priority: optional
|
||||
Architecture: any
|
||||
Depends: zoneminder (= ${binary:Version}), ${misc:Depends}
|
||||
Description: Zoneminder -- debugging symbols
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: ZoneMinder
|
||||
Upstream-Contact: Philip Coombes <philip.coombes@zoneminder.com>
|
||||
Upstream-Contact: Isaac Connor <isaac@zoneminder.com>
|
||||
Source: https://github.com/ZoneMinder/ZoneMinder
|
||||
Comment:
|
||||
This package was originally debianized by matrix <matrix@cecilia>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
@ -12,13 +11,14 @@ ARGS:= -DZM_NO_MMAP=ON
|
|||
endif
|
||||
|
||||
%:
|
||||
dh $@ --parallel --buildsystem=cmake --builddirectory=dbuild \
|
||||
--with systemd,sphinxdoc,apache2,linktree
|
||||
dh $@ --buildsystem=cmake --builddirectory=dbuild \
|
||||
--with sphinxdoc,apache2,linktree
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- $(ARGS) \
|
||||
-DCMAKE_VERBOSE_MAKEFILE=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DBUILD_MAN=0 \
|
||||
-DZM_CONFIG_DIR="/etc/zm" \
|
||||
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
|
||||
-DZM_RUNDIR="/run/zm" \
|
||||
|
@ -34,11 +34,26 @@ override_dh_clean:
|
|||
dh_clean $(MANPAGES1)
|
||||
$(RM) -r docs/_build
|
||||
|
||||
build-indep:
|
||||
#$(MAKE) -C docs text
|
||||
override_dh_auto_build-indep:
|
||||
$(MAKE) -C docs html
|
||||
dh_auto_build
|
||||
|
||||
MANPAGES1 = \
|
||||
dbuild/scripts/zmupdate.pl.1 \
|
||||
dbuild/scripts/zmaudit.pl.1 \
|
||||
dbuild/scripts/zmcamtool.pl.1 \
|
||||
dbuild/scripts/zmcontrol.pl.1 \
|
||||
dbuild/scripts/zmdc.pl.1 \
|
||||
dbuild/scripts/zmfilter.pl.1 \
|
||||
dbuild/scripts/zmpkg.pl.1 \
|
||||
dbuild/scripts/zmsystemctl.pl.1 \
|
||||
dbuild/scripts/zmtelemetry.pl.1 \
|
||||
dbuild/scripts/zmtrack.pl.1 \
|
||||
dbuild/scripts/zmtrigger.pl.1 \
|
||||
dbuild/scripts/zmvideo.pl.1 \
|
||||
dbuild/scripts/zmwatch.pl.1 \
|
||||
dbuild/scripts/zmx10.pl.1
|
||||
|
||||
MANPAGES1 = dbuild/scripts/zmupdate.pl.1
|
||||
$(MANPAGES1):
|
||||
# generate man page(s):
|
||||
pod2man -s1 --stderr --utf8 $(patsubst %.1, %, $@) $@
|
||||
|
@ -51,7 +66,7 @@ override_dh_installman: $(MANPAGES1)
|
|||
dh_installman --language=C $(MANPAGES1)
|
||||
|
||||
override_dh_auto_install:
|
||||
dh_auto_install --destdir=$(CURDIR)/debian/tmp
|
||||
dh_auto_install --arch --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
|
||||
|
@ -67,11 +82,11 @@ override_dh_fixperms:
|
|||
chown root:www-data $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
chmod 640 $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
|
||||
override_dh_systemd_start:
|
||||
dh_systemd_start --no-start
|
||||
override_dh_installinit:
|
||||
dh_installinit --no-start
|
||||
|
||||
override_dh_systemd_enable:
|
||||
dh_systemd_enable --no-enable
|
||||
override_dh_installsystemd:
|
||||
dh_installsystemd --no-enable --no-start
|
||||
|
||||
override_dh_apache2:
|
||||
dh_apache2 --noenable
|
||||
|
@ -81,16 +96,3 @@ override_dh_strip:
|
|||
&& 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
|
||||
|
|
|
@ -6,7 +6,9 @@ usr/share/polkit-1
|
|||
usr/share/zoneminder/db
|
||||
usr/share/zoneminder/www
|
||||
usr/share/zoneminder/fonts
|
||||
usr/share/zoneminder/icons
|
||||
usr/share/applications/*
|
||||
|
||||
# libzoneminder-perl files:
|
||||
usr/share/man/man3
|
||||
#usr/share/man/man3
|
||||
usr/share/perl5
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
## cakephp
|
||||
#replace /usr/share/php/Cake /usr/share/zoneminder/www/api/lib/Cake
|
||||
|
||||
## libjs-jquery
|
||||
replace /usr/share/javascript/jquery/jquery.min.js /usr/share/zoneminder/www/skins/classic/js/jquery-3.5.1.min.js
|
||||
replace /usr/share/javascript/jquery/jquery.min.js /usr/share/zoneminder/www/skins/flat/js/jquery-3.5.1.min.js
|
|
@ -52,7 +52,10 @@ if [ "$1" = "configure" ]; then
|
|||
chown www-data:www-data /var/cache/zoneminder /var/cache/zoneminder/*
|
||||
if [ ! -e "/etc/apache2/mods-enabled/cgi.load" ] && [ "$(command -v a2enmod)" != "" ]; then
|
||||
echo "The cgi module is not enabled in apache2. I am enabling it using a2enmod cgi."
|
||||
a2enmod cgi
|
||||
if [ -e /usr/share/apache2/apache2-maintscript-helper ] ; then
|
||||
. /usr/share/apache2/apache2-maintscript-helper
|
||||
apache2_invoke enmod cgi || exit $?
|
||||
fi
|
||||
fi
|
||||
|
||||
SYSTEMD=0
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
import sys
|
||||
import os
|
||||
|
||||
def setup(app):
|
||||
app.add_stylesheet('zmstyle.css')
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
|
@ -134,7 +131,9 @@ html_theme = 'default'
|
|||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
#html_style='zmstyles.css'
|
||||
|
||||
html_css_files = [ 'zmstyle.css' ]
|
||||
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
|
|
|
@ -184,6 +184,7 @@ sub moveVector {
|
|||
# Send it to the camera
|
||||
$self->PutCmd($command,$xml);
|
||||
}
|
||||
sub zoomStop { $_[0]->moveVector( 0, 0, 0, splice(@_,1)); }
|
||||
sub moveStop { $_[0]->moveVector( 0, 0, 0, splice(@_,1)); }
|
||||
sub moveConUp { $_[0]->moveVector( 0, 1, 0, splice(@_,1)); }
|
||||
sub moveConUpRight { $_[0]->moveVector( 1, 1, 0, splice(@_,1)); }
|
||||
|
|
|
@ -144,8 +144,8 @@ our $mem_seq = 0;
|
|||
our $mem_data = {
|
||||
shared_data => { type=>'SharedData', seq=>$mem_seq++, contents=> {
|
||||
size => { type=>'uint32', seq=>$mem_seq++ },
|
||||
last_write_index => { type=>'uint32', seq=>$mem_seq++ },
|
||||
last_read_index => { type=>'uint32', seq=>$mem_seq++ },
|
||||
last_write_index => { type=>'int32', seq=>$mem_seq++ },
|
||||
last_read_index => { type=>'int32', seq=>$mem_seq++ },
|
||||
state => { type=>'uint32', seq=>$mem_seq++ },
|
||||
capture_fps => { type=>'double', seq=>$mem_seq++ },
|
||||
analysis_fps => { type=>'double', seq=>$mem_seq++ },
|
||||
|
@ -162,7 +162,7 @@ our $mem_data = {
|
|||
signal => { type=>'uint8', seq=>$mem_seq++ },
|
||||
format => { type=>'uint8', seq=>$mem_seq++ },
|
||||
imagesize => { type=>'uint32', seq=>$mem_seq++ },
|
||||
epadding1 => { type=>'uint32', seq=>$mem_seq++ },
|
||||
last_frame_score => { type=>'uint32', seq=>$mem_seq++ },
|
||||
startup_time => { type=>'time_t64', seq=>$mem_seq++ },
|
||||
zmc_heartbeat_time => { type=>'time_t64', seq=>$mem_seq++ },
|
||||
zma_heartbeat_time => { type=>'time_t64', seq=>$mem_seq++ },
|
||||
|
|
|
@ -92,7 +92,6 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
|
|||
|
||||
my @daemons = (
|
||||
'zmc',
|
||||
#'zma',
|
||||
'zmfilter.pl',
|
||||
'zmaudit.pl',
|
||||
'zmtrigger.pl',
|
||||
|
|
|
@ -360,6 +360,7 @@ sub checkFilter {
|
|||
|
||||
if ( $filter->{AutoMove} ) {
|
||||
my $NewStorage = new ZoneMinder::Storage($filter->{AutoMoveTo});
|
||||
Info("Moving event $Event->{Id} to datastore $filter->{AutoMoveTo}");
|
||||
$_ = $Event->MoveTo($NewStorage);
|
||||
Error($_) if $_;
|
||||
}
|
||||
|
@ -368,6 +369,7 @@ sub checkFilter {
|
|||
# So we still need to update the Event object with the new SecondaryStorageId
|
||||
my $NewStorage = ZoneMinder::Storage->find_one(Id=>$filter->{AutoCopyTo});
|
||||
if ( $NewStorage ) {
|
||||
Info("Copying event $Event->{Id} to datastore $filter->{AutoCopyTo}");
|
||||
$_ = $Event->CopyTo($NewStorage);
|
||||
if ( $_ ) {
|
||||
$ZoneMinder::Database::dbh->commit();
|
||||
|
|
|
@ -224,6 +224,7 @@ Debug("@Monitors");
|
|||
$$Event{RelativePath} = join('/', $day_dir, $event_path);
|
||||
$$Event{Scheme} = 'Deep';
|
||||
$$Event{Name} = "Event $event_id recovered";
|
||||
$$Event{StateId} = 1;
|
||||
$Event->MonitorId( $monitor_dir );
|
||||
$Event->StorageId( $Storage->Id() );
|
||||
$Event->DiskSpace( undef );
|
||||
|
@ -287,6 +288,7 @@ Debug("@Monitors");
|
|||
$$Event{RelativePath} = join('/', $day_dir, $event_dir);
|
||||
$$Event{Scheme} = 'Deep';
|
||||
$$Event{Name} = "Event $event_id recovered";
|
||||
$$Event{StateId} = 1;
|
||||
$Event->MonitorId( $monitor_dir );
|
||||
$Event->Width( $Monitor->Width() );
|
||||
$Event->Height( $Monitor->Height() );
|
||||
|
@ -352,6 +354,7 @@ Debug("@Monitors");
|
|||
$$Event{Scheme} = 'Medium';
|
||||
$$Event{RelativePath} = $event_dir;
|
||||
$$Event{Name} = "Event $event_id recovered";
|
||||
$$Event{StateId} = 1;
|
||||
$Event->MonitorId( $monitor_dir );
|
||||
$Event->Width( $Monitor->Width() );
|
||||
$Event->Height( $Monitor->Height() );
|
||||
|
@ -393,6 +396,7 @@ Debug("@Monitors");
|
|||
if ( confirm() ) {
|
||||
$$Event{Scheme} = 'Shallow';
|
||||
$$Event{Name} = "Event $event recovered";
|
||||
$$Event{StateId} = 1;
|
||||
#$$Event{Path} = $event_path;
|
||||
$Event->MonitorId( $monitor_dir );
|
||||
$Event->Width( $Monitor->Width() );
|
||||
|
|
|
@ -9,7 +9,7 @@ AnalysisThread::AnalysisThread(std::shared_ptr<Monitor> monitor) :
|
|||
}
|
||||
|
||||
AnalysisThread::~AnalysisThread() {
|
||||
terminate_ = true;
|
||||
Stop();
|
||||
if (thread_.joinable())
|
||||
thread_.join();
|
||||
}
|
||||
|
@ -40,10 +40,11 @@ void AnalysisThread::Run() {
|
|||
|
||||
Debug(2, "Analyzing");
|
||||
if (!monitor_->Analyse()) {
|
||||
Microseconds sleep_for = monitor_->Active() ? Microseconds(ZM_SAMPLE_RATE) : Microseconds(ZM_SUSPENDED_RATE);
|
||||
|
||||
Debug(2, "Sleeping for %" PRId64 "us", int64(sleep_for.count()));
|
||||
std::this_thread::sleep_for(sleep_for);
|
||||
if ( !(terminate_ or zm_terminate) ) {
|
||||
Microseconds sleep_for = monitor_->Active() ? Microseconds(ZM_SAMPLE_RATE) : Microseconds(ZM_SUSPENDED_RATE);
|
||||
Debug(2, "Sleeping for %" PRId64 "us", int64(sleep_for.count()));
|
||||
std::this_thread::sleep_for(sleep_for);
|
||||
}
|
||||
} else if (analysis_rate != Microseconds::zero()) {
|
||||
Debug(2, "Sleeping for %" PRId64 " us", int64(analysis_rate.count()));
|
||||
std::this_thread::sleep_for(analysis_rate);
|
||||
|
|
|
@ -13,6 +13,8 @@ class AnalysisThread {
|
|||
AnalysisThread(AnalysisThread &rhs) = delete;
|
||||
AnalysisThread(AnalysisThread &&rhs) = delete;
|
||||
|
||||
void Stop() { terminate_ = true; }
|
||||
|
||||
private:
|
||||
void Run();
|
||||
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
#define ZM_CAMERA_H
|
||||
|
||||
#include "zm_image.h"
|
||||
#include "zm_monitor.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
class Monitor;
|
||||
class ZMPacket;
|
||||
|
||||
//
|
||||
|
@ -76,7 +76,6 @@ public:
|
|||
);
|
||||
virtual ~Camera();
|
||||
|
||||
unsigned int getId() const { return monitor->Id(); }
|
||||
SourceType Type() const { return type; }
|
||||
bool IsLocal() const { return type == LOCAL_SRC; }
|
||||
bool IsRemote() const { return type == REMOTE_SRC; }
|
||||
|
|
|
@ -175,6 +175,37 @@ MYSQL_RES *zmDbRow::fetch(const char *query) {
|
|||
return result_set;
|
||||
}
|
||||
|
||||
int zmDbDo(const char *query) {
|
||||
db_mutex.lock();
|
||||
int rc;
|
||||
while ( rc = mysql_query(&dbconn, query) ) {
|
||||
db_mutex.unlock();
|
||||
Error("Can't run query %s: %s", query, mysql_error(&dbconn));
|
||||
if ( (mysql_errno(&dbconn) != ER_LOCK_WAIT_TIMEOUT) )
|
||||
return rc;
|
||||
|
||||
db_mutex.lock();
|
||||
}
|
||||
db_mutex.unlock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zmDbDoInsert(const char *query) {
|
||||
db_mutex.lock();
|
||||
int rc;
|
||||
while ( rc = mysql_query(&dbconn, query) ) {
|
||||
db_mutex.unlock();
|
||||
Error("Can't run query %s: %s", query, mysql_error(&dbconn));
|
||||
if ( (mysql_errno(&dbconn) != ER_LOCK_WAIT_TIMEOUT) )
|
||||
return 0;
|
||||
|
||||
db_mutex.lock();
|
||||
}
|
||||
int id = mysql_insert_id(&dbconn);
|
||||
db_mutex.unlock();
|
||||
return id;
|
||||
}
|
||||
|
||||
zmDbRow::~zmDbRow() {
|
||||
if ( result_set ) {
|
||||
mysql_free_result(result_set);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "zm_thread.h"
|
||||
#include <mysql/mysql.h>
|
||||
#include <mysql/mysqld_error.h>
|
||||
|
||||
class zmDbRow {
|
||||
private:
|
||||
|
@ -47,6 +48,8 @@ extern bool zmDbConnected;
|
|||
|
||||
bool zmDbConnect();
|
||||
void zmDbClose();
|
||||
int zmDbDo(const char *query);
|
||||
int zmDbDoInsert(const char *query);
|
||||
|
||||
MYSQL_RES * zmDbFetch( const char *query );
|
||||
zmDbRow *zmDbFetchOne( const char *query );
|
||||
|
|
|
@ -105,8 +105,7 @@ Event::Event(
|
|||
save_jpegs = monitor->GetOptSaveJPEGs();
|
||||
Storage * storage = monitor->getStorage();
|
||||
|
||||
char sql[ZM_SQL_MED_BUFSIZ];
|
||||
snprintf(sql, sizeof(sql),
|
||||
std::string sql = stringtf(
|
||||
"INSERT INTO `Events` "
|
||||
"( `MonitorId`, `StorageId`, `Name`, `StartDateTime`, `Width`, `Height`, `Cause`, `Notes`, `StateId`, `Orientation`, `Videoed`, `DefaultVideo`, `SaveJPEGs`, `Scheme` )"
|
||||
" VALUES "
|
||||
|
@ -120,25 +119,19 @@ Event::Event(
|
|||
notes.c_str(),
|
||||
state_id,
|
||||
monitor->getOrientation(),
|
||||
( monitor->GetOptVideoWriter() != 0 ? 1 : 0 ),
|
||||
( monitor->GetOptVideoWriter() != 0 ? "video.mp4" : "" ),
|
||||
monitor->GetOptSaveJPEGs(),
|
||||
0,
|
||||
"",
|
||||
save_jpegs,
|
||||
storage->SchemeString().c_str()
|
||||
);
|
||||
|
||||
db_mutex.lock();
|
||||
while ( mysql_query(&dbconn, sql) ) {
|
||||
db_mutex.unlock();
|
||||
Error("Can't insert event: %s. sql was (%s)", mysql_error(&dbconn), sql);
|
||||
db_mutex.lock();
|
||||
}
|
||||
id = mysql_insert_id(&dbconn);
|
||||
id = zmDbDoInsert(sql.c_str());
|
||||
|
||||
if ( !SetPath(storage) ) {
|
||||
// Try another
|
||||
Warning("Failed creating event dir at %s", storage->Path());
|
||||
|
||||
std::string sql = stringtf("SELECT `Id` FROM `Storage` WHERE `Id` != %u", storage->Id());
|
||||
sql = stringtf("SELECT `Id` FROM `Storage` WHERE `Id` != %u", storage->Id());
|
||||
if ( monitor->ServerId() )
|
||||
sql += stringtf(" AND ServerId=%u", monitor->ServerId());
|
||||
|
||||
|
@ -182,16 +175,10 @@ Event::Event(
|
|||
Warning("Failed to find a storage area to save events.");
|
||||
}
|
||||
sql = stringtf("UPDATE Events SET StorageId = '%d' WHERE Id=%" PRIu64, storage->Id(), id);
|
||||
db_mutex.lock();
|
||||
int rc = mysql_query(&dbconn, sql.c_str());
|
||||
db_mutex.unlock();
|
||||
if ( rc ) {
|
||||
Error("Can't update event: %s. sql was (%s)", mysql_error(&dbconn), sql.c_str());
|
||||
}
|
||||
}
|
||||
zmDbDo(sql.c_str());
|
||||
} // end if ! setPath(Storage)
|
||||
Debug(1, "Using storage area at %s", path.c_str());
|
||||
|
||||
db_mutex.unlock();
|
||||
video_name = "";
|
||||
|
||||
snapshot_file = path + "/snapshot.jpg";
|
||||
|
@ -202,38 +189,33 @@ Event::Event(
|
|||
if ( monitor->GetOptVideoWriter() != 0 ) {
|
||||
std::string container = monitor->OutputContainer();
|
||||
if ( container == "auto" || container == "" ) {
|
||||
if ( monitor->OutputCodec() == AV_CODEC_ID_H264 ) {
|
||||
container = "mp4";
|
||||
} else {
|
||||
container = "mkv";
|
||||
}
|
||||
container = "mp4";
|
||||
}
|
||||
|
||||
video_name = stringtf("%" PRIu64 "-%s.%s", id, "video", container.c_str());
|
||||
snprintf(sql, sizeof(sql), "UPDATE Events SET DefaultVideo = '%s' WHERE Id=%" PRIu64, video_name.c_str(), id);
|
||||
db_mutex.lock();
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
db_mutex.unlock();
|
||||
Error("Can't update event: %s. sql was (%s)", mysql_error(&dbconn), sql);
|
||||
return;
|
||||
}
|
||||
db_mutex.unlock();
|
||||
video_file = path + "/" + video_name;
|
||||
Debug(1, "Writing video file to %s", video_file.c_str());
|
||||
Camera * camera = monitor->getCamera();
|
||||
videoStore = new VideoStore(
|
||||
video_file.c_str(),
|
||||
container.c_str(),
|
||||
camera->get_VideoStream(),
|
||||
camera->get_VideoCodecContext(),
|
||||
( monitor->RecordAudio() ? camera->get_AudioStream() : nullptr ),
|
||||
( monitor->RecordAudio() ? camera->get_AudioCodecContext() : nullptr ),
|
||||
monitor->GetVideoStream(),
|
||||
monitor->GetVideoCodecContext(),
|
||||
( monitor->RecordAudio() ? monitor->GetAudioStream() : nullptr ),
|
||||
( monitor->RecordAudio() ? monitor->GetAudioCodecContext() : nullptr ),
|
||||
monitor );
|
||||
|
||||
if ( !videoStore->open() ) {
|
||||
Warning("Failed to open videostore, turning on jpegs");
|
||||
delete videoStore;
|
||||
videoStore = nullptr;
|
||||
save_jpegs |= 1; // Turn on jpeg storage
|
||||
if ( ! ( save_jpegs & 1 ) ) {
|
||||
save_jpegs |= 1; // Turn on jpeg storage
|
||||
sql = stringtf("UPDATE Events SET SaveJpegs=%d WHERE Id=%" PRIu64, save_jpegs, id);
|
||||
zmDbDo(sql.c_str());
|
||||
}
|
||||
} else {
|
||||
sql = stringtf("UPDATE Events SET Videoed=1, DefaultVideo = '%s' WHERE Id=%" PRIu64, video_name.c_str(), id);
|
||||
zmDbDo(sql.c_str());
|
||||
}
|
||||
} // end if GetOptVideoWriter
|
||||
} // Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap, bool p_videoEvent )
|
||||
|
@ -621,8 +603,8 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
|
|||
( ! (frames % config.bulk_frame_interval) )
|
||||
) ? BULK : NORMAL
|
||||
) );
|
||||
//Debug(1, "Have frame type %s from score(%d) state %d frames %d bulk frame interval %d and mod%d",
|
||||
//frame_type_names[frame_type], score, monitor->GetState(), frames, config.bulk_frame_interval, (frames % config.bulk_frame_interval) );
|
||||
Debug(1, "Have frame type %s from score(%d) state %d frames %d bulk frame interval %d and mod%d",
|
||||
frame_type_names[frame_type], score, monitor->GetState(), frames, config.bulk_frame_interval, (frames % config.bulk_frame_interval) );
|
||||
|
||||
if ( score < 0 )
|
||||
score = 0;
|
||||
|
@ -662,6 +644,8 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
|
|||
}
|
||||
}
|
||||
} // end if is an alarm frame
|
||||
} else {
|
||||
Debug(1, "No image");
|
||||
} // end if has image
|
||||
|
||||
bool db_frame = ( frame_type == BULK ) or ( frame_type == ALARM ) or ( frames == 1 ) or ( score > (int)max_score ) or ( monitor_state == Monitor::ALERT ) or ( monitor_state == Monitor::PREALARM );
|
||||
|
|
|
@ -374,23 +374,19 @@ int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void fix_deprecated_pix_fmt(AVCodecContext *ctx) {
|
||||
enum AVPixelFormat fix_deprecated_pix_fmt(enum AVPixelFormat fmt) {
|
||||
// Fix deprecated formats
|
||||
switch ( ctx->pix_fmt ) {
|
||||
switch ( fmt ) {
|
||||
case AV_PIX_FMT_YUVJ422P :
|
||||
ctx->pix_fmt = AV_PIX_FMT_YUV422P;
|
||||
break;
|
||||
return AV_PIX_FMT_YUV422P;
|
||||
case AV_PIX_FMT_YUVJ444P :
|
||||
ctx->pix_fmt = AV_PIX_FMT_YUV444P;
|
||||
break;
|
||||
return AV_PIX_FMT_YUV444P;
|
||||
case AV_PIX_FMT_YUVJ440P :
|
||||
ctx->pix_fmt = AV_PIX_FMT_YUV440P;
|
||||
break;
|
||||
return AV_PIX_FMT_YUV440P;
|
||||
case AV_PIX_FMT_NONE :
|
||||
case AV_PIX_FMT_YUVJ420P :
|
||||
default:
|
||||
ctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
break;
|
||||
return AV_PIX_FMT_YUV420P;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -423,7 +423,7 @@ void zm_dump_codecpar(const AVCodecParameters *par);
|
|||
#endif
|
||||
|
||||
int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt);
|
||||
void fix_deprecated_pix_fmt(AVCodecContext *);
|
||||
enum AVPixelFormat fix_deprecated_pix_fmt(enum AVPixelFormat );
|
||||
|
||||
bool is_video_stream(const AVStream *);
|
||||
bool is_audio_stream(const AVStream *);
|
||||
|
|
|
@ -280,7 +280,7 @@ void Image::Assign(const AVFrame *frame) {
|
|||
#if HAVE_LIBSWSCALE
|
||||
sws_convert_context = sws_getCachedContext(
|
||||
sws_convert_context,
|
||||
width, height, (AVPixelFormat)frame->format,
|
||||
frame->width, frame->height, (AVPixelFormat)frame->format,
|
||||
width, height, format,
|
||||
SWS_BICUBIC, nullptr, nullptr, nullptr);
|
||||
if ( sws_convert_context == nullptr )
|
||||
|
|
|
@ -36,17 +36,16 @@ void bind_libvnc_symbols() {
|
|||
*(void**) (&HandleRFBServerMessage_f) = dlsym(libvnc_lib, "HandleRFBServerMessage");
|
||||
}
|
||||
|
||||
static void GotFrameBufferUpdateCallback(rfbClient *rfb, int x, int y, int w, int h){
|
||||
static void GotFrameBufferUpdateCallback(rfbClient *rfb, int x, int y, int w, int h) {
|
||||
VncPrivateData *data = (VncPrivateData *)(*rfbClientGetClientData_f)(rfb, &TAG_0);
|
||||
data->buffer = rfb->frameBuffer;
|
||||
Debug(1, "GotFrameBufferUpdateallback x:%d y:%d w%d h:%d width: %d, height: %d",
|
||||
x,y,w,h, rfb->width, rfb->height);
|
||||
Debug(1, "GotFrameBufferUpdateallback x:%d y:%d w%d h:%d width: %d, height: %d, buffer %p",
|
||||
x,y,w,h, rfb->width, rfb->height, rfb->frameBuffer);
|
||||
}
|
||||
|
||||
static char* GetPasswordCallback(rfbClient* cl){
|
||||
Debug(1, "Getcredentials: %s", (*rfbClientGetClientData_f)(cl, &TAG_1));
|
||||
return strdup(
|
||||
(const char *)(*rfbClientGetClientData_f)(cl, &TAG_1));
|
||||
return strdup((const char *)(*rfbClientGetClientData_f)(cl, &TAG_1));
|
||||
}
|
||||
|
||||
static rfbCredential* GetCredentialsCallback(rfbClient* cl, int credentialType){
|
||||
|
@ -102,15 +101,12 @@ VncCamera::VncCamera(
|
|||
if ( colours == ZM_COLOUR_RGB32 ) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
mImgPixFmt = AV_PIX_FMT_RGBA;
|
||||
mBpp = 4;
|
||||
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
mImgPixFmt = AV_PIX_FMT_RGB24;
|
||||
mBpp = 3;
|
||||
} else if ( colours == ZM_COLOUR_GRAY8 ) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
mImgPixFmt = AV_PIX_FMT_GRAY8;
|
||||
mBpp = 1;
|
||||
} else {
|
||||
Panic("Unexpected colours: %d", colours);
|
||||
}
|
||||
|
@ -119,7 +115,6 @@ VncCamera::VncCamera(
|
|||
Debug(3, "Initializing Client");
|
||||
bind_libvnc_symbols();
|
||||
scale.init();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,13 +129,16 @@ VncCamera::~VncCamera() {
|
|||
int VncCamera::PrimeCapture() {
|
||||
Debug(1, "Priming capture from %s", mHost.c_str());
|
||||
|
||||
if ( ! mRfb ) {
|
||||
if (!mRfb) {
|
||||
mVncData.buffer = nullptr;
|
||||
mVncData.width = 0;
|
||||
mVncData.height = 0;
|
||||
|
||||
mBufferSize = SWScale::GetBufferSize(AV_PIX_FMT_RGBA, width, height);
|
||||
|
||||
mRfb = (*rfbGetClient_f)(8 /* bits per sample */, 3 /* samples per pixel */, 4 /* bytes Per Pixel */);
|
||||
mRfb->frameBuffer = (uint8_t *)av_malloc(8*4*width*height);
|
||||
mRfb->frameBuffer = nullptr;
|
||||
//(uint8_t *)av_malloc(mBufferSize);
|
||||
mRfb->canHandleNewFBSize = false;
|
||||
|
||||
(*rfbClientSetClientData_f)(mRfb, &TAG_0, &mVncData);
|
||||
|
@ -157,7 +155,7 @@ int VncCamera::PrimeCapture() {
|
|||
}
|
||||
if ( ! (*rfbInitClient_f)(mRfb, 0, nullptr) ) {
|
||||
/* IF rfbInitClient fails, it calls rdbClientCleanup which will free mRfb */
|
||||
Warning("Failed to Priming capture from %s", mHost.c_str());
|
||||
Warning("Failed to Prime capture from %s", mHost.c_str());
|
||||
mRfb = nullptr;
|
||||
return -1;
|
||||
}
|
||||
|
@ -165,8 +163,9 @@ int VncCamera::PrimeCapture() {
|
|||
Warning("Specified dimensions do not match screen size monitor: (%dx%d) != vnc: (%dx%d)",
|
||||
width, height, mRfb->width, mRfb->height);
|
||||
}
|
||||
get_VideoStream();
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int VncCamera::PreCapture() {
|
||||
|
@ -182,15 +181,24 @@ int VncCamera::PreCapture() {
|
|||
}
|
||||
|
||||
int VncCamera::Capture(ZMPacket &zm_packet) {
|
||||
if ( ! mVncData.buffer ) {
|
||||
if ( !mVncData.buffer ) {
|
||||
Debug(1, "No buffer");
|
||||
return 0;
|
||||
}
|
||||
if ( !zm_packet.image ) {
|
||||
Debug(1, "Allocating image %dx%d %dcolours = %d", width, height, colours, pixels);
|
||||
zm_packet.image = new Image(width, height, colours, subpixelorder);
|
||||
}
|
||||
zm_packet.keyframe = 1;
|
||||
zm_packet.codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
zm_packet.packet.stream_index = mVideoStreamId;
|
||||
|
||||
uint8_t *directbuffer = zm_packet.image->WriteBuffer(width, height, colours, subpixelorder);
|
||||
int rc = scale.Convert(
|
||||
mVncData.buffer,
|
||||
mRfb->si.framebufferHeight * mRfb->si.framebufferWidth * 4,
|
||||
directbuffer,
|
||||
width * height * mBpp,
|
||||
width * height * colours,
|
||||
AV_PIX_FMT_RGBA,
|
||||
mImgPixFmt,
|
||||
mRfb->si.framebufferWidth,
|
||||
|
@ -201,10 +209,10 @@ int VncCamera::Capture(ZMPacket &zm_packet) {
|
|||
}
|
||||
|
||||
int VncCamera::PostCapture() {
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int VncCamera::Close() {
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,13 @@
|
|||
#if HAVE_LIBVNC
|
||||
#include <rfb/rfbclient.h>
|
||||
|
||||
// Older versions of libvncserver defined a max macro in rfb/rfbproto.h
|
||||
// Undef it here so it doesn't collide with std::max
|
||||
// TODO: Remove this once xenial support is dropped
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
// Used by vnc callbacks
|
||||
struct VncPrivateData {
|
||||
uint8_t *buffer;
|
||||
|
@ -19,7 +26,7 @@ class VncCamera : public Camera {
|
|||
protected:
|
||||
rfbClient *mRfb;
|
||||
VncPrivateData mVncData;
|
||||
int mBpp;
|
||||
int mBufferSize;
|
||||
SWScale scale;
|
||||
AVPixelFormat mImgPixFmt;
|
||||
std::string mHost;
|
||||
|
|
|
@ -946,12 +946,12 @@ void LocalCamera::Initialise() {
|
|||
}
|
||||
|
||||
if ( (input.std != V4L2_STD_UNKNOWN) && ((input.std & standard) == V4L2_STD_UNKNOWN) ) {
|
||||
Fatal("Device does not support video standard %d", standard);
|
||||
Error("Device does not support video standard %d", standard);
|
||||
}
|
||||
|
||||
stdId = standard;
|
||||
if ( (input.std != V4L2_STD_UNKNOWN) && (vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0) ) {
|
||||
Fatal("Failed to set video standard %d: %d %s", standard, errno, strerror(errno));
|
||||
if ((vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0)) {
|
||||
Error("Failed to set video standard %d: %d %s", standard, errno, strerror(errno));
|
||||
}
|
||||
|
||||
Contrast(contrast);
|
||||
|
@ -2201,7 +2201,6 @@ int LocalCamera::PostCapture() {
|
|||
v4l2_std_id stdId = standards[next_channel];
|
||||
if ( vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0 ) {
|
||||
Error("Failed to set video format %d: %s", standards[next_channel], strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if ( v4l2_data.bufptr ) {
|
||||
|
|
1343
src/zm_monitor.cpp
1343
src/zm_monitor.cpp
File diff suppressed because it is too large
Load Diff
|
@ -21,6 +21,7 @@
|
|||
#define ZM_MONITOR_H
|
||||
|
||||
#include "zm_define.h"
|
||||
#include "zm_camera.h"
|
||||
#include "zm_event.h"
|
||||
#include "zm_image.h"
|
||||
#include "zm_packet.h"
|
||||
|
@ -30,7 +31,6 @@
|
|||
#include <sys/time.h>
|
||||
#include <vector>
|
||||
|
||||
class Camera;
|
||||
class Group;
|
||||
|
||||
#define SIGNAL_CAUSE "Signal"
|
||||
|
@ -105,8 +105,8 @@ protected:
|
|||
/* sizeof(SharedData) expected to be 344 bytes on 32bit and 64bit */
|
||||
typedef struct {
|
||||
uint32_t size; /* +0 */
|
||||
uint32_t last_write_index; /* +4 */
|
||||
uint32_t last_read_index; /* +8 */
|
||||
int32_t last_write_index; /* +4 */
|
||||
int32_t last_read_index; /* +8 */
|
||||
uint32_t state; /* +12 */
|
||||
double capture_fps; // Current capturing fps
|
||||
double analysis_fps; // Current analysis fps
|
||||
|
@ -286,7 +286,7 @@ protected:
|
|||
char label_format[64]; // The format of the timestamp on the images
|
||||
Coord label_coord; // The coordinates of the timestamp on the images
|
||||
int label_size; // Size of the timestamp on the images
|
||||
int image_buffer_count; // Size of circular image buffer, at least twice the size of the pre_event_count
|
||||
int32_t image_buffer_count; // Size of circular image buffer, at least twice the size of the pre_event_count
|
||||
int pre_event_buffer_count; // Size of dedicated circular pre event buffer used when analysis is not performed at capturing framerate,
|
||||
// value is pre_event_count + alarm_frame_count - 1
|
||||
int warmup_count; // How many images to process before looking for events
|
||||
|
@ -358,14 +358,15 @@ protected:
|
|||
int video_stream_id; // will be filled in PrimeCapture
|
||||
int audio_stream_id; // will be filled in PrimeCapture
|
||||
|
||||
Camera *camera;
|
||||
std::unique_ptr<Camera> camera;
|
||||
Event *event;
|
||||
std::mutex event_mutex;
|
||||
Storage *storage;
|
||||
|
||||
VideoStore *videoStore;
|
||||
PacketQueue packetqueue;
|
||||
packetqueue_iterator *analysis_it;
|
||||
Mutex mutex;
|
||||
|
||||
|
||||
int n_zones;
|
||||
Zone **zones;
|
||||
|
@ -393,13 +394,14 @@ public:
|
|||
void AddZones( int p_n_zones, Zone *p_zones[] );
|
||||
void AddPrivacyBitmask( Zone *p_zones[] );
|
||||
|
||||
void LoadCamera();
|
||||
bool connect();
|
||||
bool disconnect();
|
||||
|
||||
inline int ShmValid() const {
|
||||
return shared_data && shared_data->valid;
|
||||
}
|
||||
Camera *getCamera();
|
||||
|
||||
|
||||
inline unsigned int Id() const { return id; }
|
||||
inline const char *Name() const { return name; }
|
||||
|
@ -468,10 +470,15 @@ public:
|
|||
void SetVideoWriterStartTime(const struct timeval &t) { video_store_data->recording = t; }
|
||||
|
||||
unsigned int GetPreEventCount() const { return pre_event_count; };
|
||||
int GetImageBufferCount() const { return image_buffer_count; };
|
||||
int32_t GetImageBufferCount() const { return image_buffer_count; };
|
||||
State GetState() const { return (State)shared_data->state; }
|
||||
|
||||
int GetImage( int index=-1, int scale=100 );
|
||||
AVStream *GetAudioStream() const { return camera ? camera->get_AudioStream() : nullptr; };
|
||||
AVCodecContext *GetAudioCodecContext() const { return camera ? camera->get_AudioCodecContext() : nullptr; };
|
||||
AVStream *GetVideoStream() const { return camera ? camera->get_VideoStream() : nullptr; };
|
||||
AVCodecContext *GetVideoCodecContext() const { return camera ? camera->get_VideoCodecContext() : nullptr; };
|
||||
|
||||
int GetImage(int32_t index=-1, int scale=100);
|
||||
ZMPacket *getSnapshot( int index=-1 ) const;
|
||||
struct timeval GetTimestamp( int index=-1 ) const;
|
||||
void UpdateAdaptiveSkip();
|
||||
|
|
|
@ -487,7 +487,7 @@ void MonitorStream::runStream() {
|
|||
updateFrameRate(monitor->GetFPS());
|
||||
|
||||
// point to end which is theoretically not a valid value because all indexes are % image_buffer_count
|
||||
unsigned int last_read_index = monitor->image_buffer_count;
|
||||
int32_t last_read_index = monitor->image_buffer_count;
|
||||
|
||||
time_t stream_start_time;
|
||||
time(&stream_start_time);
|
||||
|
@ -850,7 +850,13 @@ void MonitorStream::SingleImage(int scale) {
|
|||
int img_buffer_size = 0;
|
||||
static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE];
|
||||
Image scaled_image;
|
||||
ZMPacket *snap = &(monitor->image_buffer[monitor->shared_data->last_write_index]);
|
||||
while ( monitor->shared_data->last_write_index >= monitor->image_buffer_count ) {
|
||||
Debug(1, "Waiting for capture to begin");
|
||||
usleep(100000);
|
||||
}
|
||||
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count;
|
||||
Debug(1, "write index: %d %d", monitor->shared_data->last_write_index, index);
|
||||
ZMPacket *snap = &(monitor->image_buffer[index]);
|
||||
Image *snap_image = snap->image;
|
||||
|
||||
if ( scale != ZM_SCALE_BASE ) {
|
||||
|
|
|
@ -72,6 +72,14 @@ PacketQueue::~PacketQueue() {
|
|||
|
||||
bool PacketQueue::queuePacket(ZMPacket* add_packet) {
|
||||
Debug(4, "packetqueue queuepacket %p %d", add_packet, add_packet->image_index);
|
||||
if (iterators.empty()) {
|
||||
Debug(4, "No iterators so no one needs us to queue packets.");
|
||||
return false;
|
||||
}
|
||||
if (!packet_counts[video_stream_id] and !add_packet->keyframe) {
|
||||
Debug(4, "No video keyframe so no one needs us to queue packets.");
|
||||
return false;
|
||||
}
|
||||
mutex.lock();
|
||||
|
||||
pktQueue.push_back(add_packet);
|
||||
|
@ -412,6 +420,10 @@ unsigned int PacketQueue::size() {
|
|||
}
|
||||
|
||||
int PacketQueue::packet_count(int stream_id) {
|
||||
if ( stream_id < 0 or stream_id > max_stream_id ) {
|
||||
Error("Invalid stream_id %d", stream_id);
|
||||
return -1;
|
||||
}
|
||||
return packet_counts[stream_id];
|
||||
} // end int PacketQueue::packet_count(int stream_id)
|
||||
|
||||
|
@ -623,3 +635,10 @@ bool PacketQueue::is_there_an_iterator_pointing_to_packet(ZMPacket *zm_packet) {
|
|||
} // end foreach iterator
|
||||
return false;
|
||||
}
|
||||
void PacketQueue::setMaxVideoPackets(int p) {
|
||||
max_video_packet_count = p;
|
||||
Debug(1, "Setting max_video_packet_count to %d", p);
|
||||
if ( max_video_packet_count < 1 )
|
||||
max_video_packet_count = 1 ;
|
||||
// We can simplify a lot of logic in queuePacket if we can assume at least 1 packet in queue
|
||||
}
|
||||
|
|
|
@ -49,12 +49,7 @@ class PacketQueue {
|
|||
std::list<ZMPacket *>::const_iterator begin() const { return pktQueue.begin(); }
|
||||
|
||||
void addStreamId(int p_stream_id);
|
||||
void setMaxVideoPackets(int p) {
|
||||
max_video_packet_count = p;
|
||||
if ( max_video_packet_count < 1 )
|
||||
max_video_packet_count = 1 ;
|
||||
// We can simplify a lot of logic in queuePacket if we can assume at least 1 packet in queue
|
||||
}
|
||||
void setMaxVideoPackets(int p);
|
||||
|
||||
bool queuePacket(ZMPacket* packet);
|
||||
ZMPacket * popPacket();
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "zm_remote_camera_http.h"
|
||||
|
||||
#include "zm_monitor.h"
|
||||
#include "zm_packet.h"
|
||||
#include "zm_signal.h"
|
||||
#include "zm_regexp.h"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "zm_remote_camera_nvsocket.h"
|
||||
|
||||
#include "zm_monitor.h"
|
||||
#include "zm_packet.h"
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "zm_remote_camera_rtsp.h"
|
||||
|
||||
#include "zm_config.h"
|
||||
#include "zm_monitor.h"
|
||||
#include "zm_packet.h"
|
||||
|
||||
#if HAVE_LIBAVFORMAT
|
||||
|
|
|
@ -191,21 +191,11 @@ int SWScale::Convert(
|
|||
#endif
|
||||
|
||||
/* Check the buffer sizes */
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
size_t insize = av_image_get_buffer_size(in_pf, width, height, 32);
|
||||
#else
|
||||
size_t insize = avpicture_get_size(in_pf, width, height);
|
||||
#endif
|
||||
size_t insize = GetBufferSize(in_pf, width, height);
|
||||
if ( insize != in_buffer_size ) {
|
||||
Error("The input buffer size does not match the expected size for the input format. Required: %d Available: %d", insize, in_buffer_size);
|
||||
return -4;
|
||||
Debug(1, "The input buffer size does not match the expected size for the input format. Required: %d Available: %d", insize, in_buffer_size);
|
||||
}
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
size_t outsize = av_image_get_buffer_size(out_pf, new_width, new_height, 32);
|
||||
#else
|
||||
size_t outsize = avpicture_get_size(out_pf, new_width, new_height);
|
||||
#endif
|
||||
|
||||
size_t outsize = GetBufferSize(out_pf, new_width, new_height);
|
||||
if ( outsize < out_buffer_size ) {
|
||||
Error("The output buffer is undersized for the output format. Required: %d Available: %d", outsize, out_buffer_size);
|
||||
return -5;
|
||||
|
@ -305,4 +295,12 @@ int SWScale::ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_si
|
|||
|
||||
return Convert(in_buffer,in_buffer_size,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height);
|
||||
}
|
||||
|
||||
size_t SWScale::GetBufferSize(enum _AVPIXELFORMAT pf, unsigned int width, unsigned int height) {
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
return av_image_get_buffer_size(pf, width, height, 32);
|
||||
#else
|
||||
return outsize = avpicture_get_size(pf, width,height);
|
||||
#endif
|
||||
}
|
||||
#endif // HAVE_LIBSWSCALE && HAVE_LIBAVUTIL
|
||||
|
|
|
@ -20,6 +20,7 @@ class SWScale {
|
|||
int Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
|
||||
int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
|
||||
int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height, unsigned int new_width, unsigned int new_height);
|
||||
static size_t GetBufferSize(enum _AVPIXELFORMAT in_pf, unsigned int width, unsigned int height);
|
||||
|
||||
protected:
|
||||
bool gotdefaults;
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "zm_config.h"
|
||||
#include "zm_logger.h"
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <fcntl.h> /* Definition of AT_* constants */
|
||||
#include <sstream>
|
||||
#include <sys/stat.h>
|
||||
|
|
|
@ -138,7 +138,7 @@ bool VideoStore::open() {
|
|||
Error("Could not initialize ctx parameters");
|
||||
return false;
|
||||
}
|
||||
fix_deprecated_pix_fmt(video_out_ctx);
|
||||
video_out_ctx->pix_fmt = fix_deprecated_pix_fmt(video_out_ctx->pix_fmt);
|
||||
if ( oc->oformat->flags & AVFMT_GLOBALHEADER ) {
|
||||
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
|
||||
video_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
|
@ -164,7 +164,7 @@ bool VideoStore::open() {
|
|||
std::string wanted_encoder = monitor->Encoder();
|
||||
|
||||
for ( unsigned int i = 0; i < sizeof(codec_data) / sizeof(*codec_data); i++ ) {
|
||||
if ( wanted_encoder != "" ) {
|
||||
if ( wanted_encoder != "" and wanted_encoder != "auto" ) {
|
||||
if ( wanted_encoder != codec_data[i].codec_name ) {
|
||||
Debug(1, "Not the right codec name %s != %s", codec_data[i].codec_name, wanted_encoder.c_str());
|
||||
continue;
|
||||
|
@ -210,10 +210,12 @@ bool VideoStore::open() {
|
|||
video_out_ctx->gop_size = 12;
|
||||
video_out_ctx->max_b_frames = 1;
|
||||
|
||||
ret = av_opt_set(video_out_ctx->priv_data, "crf", "36", AV_OPT_SEARCH_CHILDREN);
|
||||
ret = av_opt_set(video_out_ctx, "crf", "36", AV_OPT_SEARCH_CHILDREN);
|
||||
if ( ret < 0 ) {
|
||||
Error("Could not set 'crf' for output codec %s.",
|
||||
codec_data[i].codec_name);
|
||||
Error("Could not set 'crf' for output codec %s. %s",
|
||||
codec_data[i].codec_name,
|
||||
av_make_error_string(ret).c_str()
|
||||
);
|
||||
}
|
||||
} else if ( video_out_ctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ) {
|
||||
/* just for testing, we also add B frames */
|
||||
|
@ -260,7 +262,7 @@ bool VideoStore::open() {
|
|||
// We allocate and copy in newer ffmpeg, so need to free it
|
||||
avcodec_free_context(&video_out_ctx);
|
||||
#endif
|
||||
video_out_ctx = nullptr;
|
||||
//video_out_ctx = nullptr;
|
||||
|
||||
return false;
|
||||
} // end if can't open codec
|
||||
|
|
194
src/zma.cpp
194
src/zma.cpp
|
@ -1,194 +0,0 @@
|
|||
//
|
||||
// ZoneMinder Analysis Daemon, $Date$, $Revision$
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
/*
|
||||
|
||||
=head1 NAME
|
||||
|
||||
zma - The ZoneMinder Analysis daemon
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
zma -m <monitor_id>
|
||||
zma --monitor <monitor_id>
|
||||
zma -h
|
||||
zma --help
|
||||
zma -v
|
||||
zma --version
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is the component that goes through the captured frames and checks them
|
||||
for motion which might generate an alarm or event. It generally keeps up with
|
||||
the Capture daemon but if very busy may skip some frames to prevent it falling
|
||||
behind.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
-m, --monitor_id - ID of the monitor to analyse
|
||||
-h, --help - Display usage information
|
||||
-v, --version - Print the installed version of ZoneMinder
|
||||
|
||||
=cut
|
||||
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
#include "zm_signal.h"
|
||||
#include "zm_monitor.h"
|
||||
#include "zm_fifo.h"
|
||||
|
||||
void Usage() {
|
||||
fprintf(stderr, "zma -m <monitor_id>\n");
|
||||
fprintf(stderr, "Options:\n");
|
||||
fprintf(stderr, " -m, --monitor <monitor_id> : Specify which monitor to use\n");
|
||||
fprintf(stderr, " -h, --help : This screen\n");
|
||||
fprintf(stderr, " -v, --version : Report the installed version of ZoneMinder\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] ) {
|
||||
self = argv[0];
|
||||
|
||||
srand(getpid() * time(nullptr));
|
||||
|
||||
int id = -1;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"monitor", 1, nullptr, 'm'},
|
||||
{"help", 0, nullptr, 'h'},
|
||||
{"version", 0, nullptr, 'v'},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
};
|
||||
|
||||
while (1) {
|
||||
int option_index = 0;
|
||||
|
||||
int c = getopt_long(argc, argv, "m:h:v", long_options, &option_index);
|
||||
if ( c == -1 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'm':
|
||||
id = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
Usage();
|
||||
break;
|
||||
case 'v':
|
||||
std::cout << ZM_VERSION << "\n";
|
||||
exit(0);
|
||||
default:
|
||||
//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( optind < argc ) {
|
||||
fprintf(stderr, "Extraneous options, ");
|
||||
while ( optind < argc )
|
||||
printf("%s ", argv[optind++]);
|
||||
printf("\n");
|
||||
Usage();
|
||||
}
|
||||
|
||||
if ( id < 0 ) {
|
||||
fprintf(stderr, "Bogus monitor %d\n", id);
|
||||
Usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char log_id_string[16];
|
||||
snprintf(log_id_string, sizeof(log_id_string), "zma_m%d", id);
|
||||
|
||||
zmLoadConfig();
|
||||
|
||||
logInit(log_id_string);
|
||||
|
||||
hwcaps_detect();
|
||||
|
||||
Monitor *monitor = Monitor::Load(id, true, Monitor::ANALYSIS);
|
||||
zmFifoDbgInit(monitor);
|
||||
|
||||
if ( monitor ) {
|
||||
Info("In mode %d/%d, warming up", monitor->GetFunction(), monitor->Enabled());
|
||||
|
||||
zmSetDefaultHupHandler();
|
||||
zmSetDefaultTermHandler();
|
||||
zmSetDefaultDieHandler();
|
||||
|
||||
sigset_t block_set;
|
||||
sigemptyset(&block_set);
|
||||
|
||||
useconds_t analysis_rate = monitor->GetAnalysisRate();
|
||||
unsigned int analysis_update_delay = monitor->GetAnalysisUpdateDelay();
|
||||
time_t last_analysis_update_time, cur_time;
|
||||
monitor->UpdateAdaptiveSkip();
|
||||
last_analysis_update_time = time(nullptr);
|
||||
|
||||
while ( !zm_terminate ) {
|
||||
if ( !monitor->ShmValid() ) {
|
||||
monitor->disconnect();
|
||||
Info("Waiting for shm to become valid");
|
||||
usleep(100000);
|
||||
monitor->connect();
|
||||
continue;
|
||||
}
|
||||
// Process the next image
|
||||
sigprocmask(SIG_BLOCK, &block_set, nullptr);
|
||||
|
||||
// Some periodic updates are required for variable capturing framerate
|
||||
if ( analysis_update_delay ) {
|
||||
cur_time = time(nullptr);
|
||||
if ( (unsigned int)( cur_time - last_analysis_update_time ) > analysis_update_delay ) {
|
||||
analysis_rate = monitor->GetAnalysisRate();
|
||||
monitor->UpdateAdaptiveSkip();
|
||||
last_analysis_update_time = cur_time;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !monitor->Analyse() ) {
|
||||
usleep(monitor->Active()?ZM_SAMPLE_RATE:ZM_SUSPENDED_RATE);
|
||||
} else if ( analysis_rate ) {
|
||||
usleep(analysis_rate);
|
||||
}
|
||||
|
||||
if ( zm_reload ) {
|
||||
monitor->Reload();
|
||||
logTerm();
|
||||
logInit(log_id_string);
|
||||
zm_reload = false;
|
||||
}
|
||||
sigprocmask(SIG_UNBLOCK, &block_set, nullptr);
|
||||
} // end while ! zm_terminate
|
||||
delete monitor;
|
||||
} else {
|
||||
fprintf(stderr, "Can't find monitor with id of %d\n", id);
|
||||
}
|
||||
Image::Deinitialise();
|
||||
logTerm();
|
||||
zmDbClose();
|
||||
return 0;
|
||||
}
|
37
src/zmc.cpp
37
src/zmc.cpp
|
@ -238,8 +238,8 @@ int main(int argc, char *argv[]) {
|
|||
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||
|
||||
for (const std::shared_ptr<Monitor> &monitor : monitors) {
|
||||
if (!monitor->getCamera()) {
|
||||
}
|
||||
monitor->LoadCamera();
|
||||
|
||||
if (!monitor->connect()) {
|
||||
Warning("Couldn't connect to monitor %d", monitor->Id());
|
||||
}
|
||||
|
@ -310,8 +310,7 @@ int main(int argc, char *argv[]) {
|
|||
#if HAVE_RTSP_SERVER
|
||||
if ( rtsp_server_threads ) {
|
||||
rtsp_server_threads[i] = new RTSPServerThread(monitors[i]);
|
||||
Camera *camera = monitors[i]->getCamera();
|
||||
rtsp_server_threads[i]->addStream(camera->get_VideoStream(), camera->get_AudioStream());
|
||||
rtsp_server_threads[i]->addStream(monitors[i]->GetVideoStream(), monitors[i]->GetAudioStream());
|
||||
rtsp_server_threads[i]->start();
|
||||
}
|
||||
#endif
|
||||
|
@ -376,17 +375,12 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
if ( zm_reload ) {
|
||||
for (std::shared_ptr<Monitor> &monitor : monitors) {
|
||||
monitor->Reload();
|
||||
}
|
||||
logTerm();
|
||||
logInit(log_id_string);
|
||||
zm_reload = false;
|
||||
} // end if zm_reload
|
||||
break;
|
||||
}
|
||||
} // end while ! zm_terminate and connected
|
||||
|
||||
// Killoff the analysis threads. Don't need them spinning while we try to reconnect
|
||||
analysis_threads.clear();
|
||||
for (std::unique_ptr<AnalysisThread> &analysis_thread: analysis_threads)
|
||||
analysis_thread->Stop();
|
||||
|
||||
for (size_t i = 0; i < monitors.size(); i++) {
|
||||
#if HAVE_RTSP_SERVER
|
||||
|
@ -399,16 +393,16 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
#if HAVE_RTSP_SERVER
|
||||
if (rtsp_server_threads) {
|
||||
rtsp_server_threads[i]->join();;
|
||||
rtsp_server_threads[i]->join();
|
||||
delete rtsp_server_threads[i];
|
||||
rtsp_server_threads[i] = nullptr;
|
||||
}
|
||||
#endif
|
||||
Camera *camera = monitors[i]->getCamera();
|
||||
Debug(1, "Closing camera");
|
||||
camera->Close();
|
||||
}
|
||||
|
||||
// Killoff the analysis threads. Don't need them spinning while we try to reconnect
|
||||
analysis_threads.clear();
|
||||
|
||||
#if HAVE_RTSP_SERVER
|
||||
if (rtsp_server_threads) {
|
||||
delete[] rtsp_server_threads;
|
||||
|
@ -424,6 +418,14 @@ int main(int argc, char *argv[]) {
|
|||
Debug(1, "Sleeping for 5");
|
||||
sleep(5);
|
||||
}
|
||||
if (zm_reload) {
|
||||
for (std::shared_ptr<Monitor> &monitor : monitors) {
|
||||
monitor->Reload();
|
||||
}
|
||||
logTerm();
|
||||
logInit(log_id_string);
|
||||
zm_reload = false;
|
||||
} // end if zm_reload
|
||||
} // end while ! zm_terminate outer connection loop
|
||||
|
||||
Debug(1,"Updating Monitor status");
|
||||
|
@ -436,7 +438,6 @@ int main(int argc, char *argv[]) {
|
|||
if (mysql_query(&dbconn, sql)) {
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
}
|
||||
monitor->disconnect();
|
||||
}
|
||||
|
||||
Image::Deinitialise();
|
||||
|
|
|
@ -80,7 +80,7 @@ fi;
|
|||
|
||||
if [ "$DISTROS" == "" ]; then
|
||||
if [ "$RELEASE" != "" ]; then
|
||||
DISTROS="xenial,bionic,focal"
|
||||
DISTROS="xenial,bionic,focal,groovy,hirsute"
|
||||
else
|
||||
DISTROS=`lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`;
|
||||
fi;
|
||||
|
|
|
@ -354,7 +354,7 @@ class Filter extends ZM_Object {
|
|||
for ( $i = 0; $i < count($terms); $i++ ) {
|
||||
$term = $terms[$i];
|
||||
if ( !empty($term['cnj']) ) {
|
||||
while( true ) {
|
||||
while ( true ) {
|
||||
if ( !count($postfixStack) ) {
|
||||
$postfixStack[] = array('type'=>'cnj', 'value'=>$term['cnj'], 'sqlValue'=>$term['cnj']);
|
||||
break;
|
||||
|
@ -518,7 +518,7 @@ class Filter extends ZM_Object {
|
|||
ZM\Error('Unknown operator in filter '.$term['op']);
|
||||
}
|
||||
|
||||
while( true ) {
|
||||
while ( true ) {
|
||||
if ( !count($postfixStack) ) {
|
||||
$postfixStack[] = array('type'=>'op', 'value'=>$term['op'], 'sqlValue'=>$sqlValue);
|
||||
break;
|
||||
|
@ -579,11 +579,6 @@ class Filter extends ZM_Object {
|
|||
case 'StartTime':
|
||||
$value = 'extract(hour_second from \''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\')';
|
||||
break;
|
||||
case 'Weekday':
|
||||
case 'EndWeekday':
|
||||
case 'StartWeekday':
|
||||
$value = 'weekday(\''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\')';
|
||||
break;
|
||||
default :
|
||||
if ( $value != 'NULL' )
|
||||
$value = dbEscape($value);
|
||||
|
|
|
@ -62,7 +62,8 @@ if ( $action == 'save' ) {
|
|||
'RecordAudio' => 0,
|
||||
'Method' => 'raw',
|
||||
'GroupIds' => array(),
|
||||
'LinkedMonitors' => array()
|
||||
'LinkedMonitors' => array(),
|
||||
'RTSPServer' => 0
|
||||
);
|
||||
|
||||
# Checkboxes don't return an element in the POST data, so won't be present in newMonitor.
|
||||
|
|
|
@ -33,15 +33,11 @@ if ( $action == 'save' ) {
|
|||
}
|
||||
$Monitor = new ZM\Monitor($mid);
|
||||
if ( $Monitor->Type() != 'WebSite' ) {
|
||||
$Monitor->zmaControl('stop');
|
||||
$Monitor->zmcControl('stop');
|
||||
}
|
||||
$Monitor->save($_REQUEST['newMonitor']);
|
||||
if ( $Monitor->Function() != 'None' && $Monitor->Type() != 'WebSite' ) {
|
||||
$Monitor->zmcControl('start');
|
||||
if ( $Monitor->Enabled() ) {
|
||||
$Monitor->zmaControl('start');
|
||||
}
|
||||
}
|
||||
} // end foreach mid
|
||||
$view = 'console';
|
||||
|
|
|
@ -56,9 +56,9 @@ if ( $action == 'delete' ) {
|
|||
}
|
||||
|
||||
$changed = false;
|
||||
while( $config = dbFetchNext($result) ) {
|
||||
while ($config = dbFetchNext($result)) {
|
||||
unset($newValue);
|
||||
if ( $config['Type'] == 'boolean' && empty($_REQUEST['newConfig'][$config['Name']]) ) {
|
||||
if ( ($config['Type'] == 'boolean') and empty($_REQUEST['newConfig'][$config['Name']]) ) {
|
||||
$newValue = 0;
|
||||
} else if ( isset($_REQUEST['newConfig'][$config['Name']]) ) {
|
||||
$newValue = preg_replace("/\r\n/", "\n", stripslashes($_REQUEST['newConfig'][$config['Name']]));
|
||||
|
@ -98,5 +98,4 @@ if ( $action == 'delete' ) {
|
|||
}
|
||||
return;
|
||||
} // end if object vs action
|
||||
|
||||
?>
|
||||
|
|
|
@ -30,6 +30,14 @@
|
|||
margin: 2px;
|
||||
text-align: center;
|
||||
}
|
||||
#definitionPanel:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#definitionPanel input[type=submit],
|
||||
#definitionPanel input[type=submit] {
|
||||
|
|
|
@ -613,7 +613,7 @@ function getEventResponse(respObj, respText) {
|
|||
} else {
|
||||
drawProgressBar();
|
||||
}
|
||||
nearEventsQuery( eventData.Id );
|
||||
nearEventsQuery(eventData.Id);
|
||||
} // end function getEventResponse
|
||||
|
||||
function eventQuery(eventId) {
|
||||
|
@ -626,10 +626,11 @@ function eventQuery(eventId) {
|
|||
.fail(logAjaxFail);
|
||||
}
|
||||
|
||||
function getNearEventsResponse( respObj, respText ) {
|
||||
function getNearEventsResponse(respObj, respText) {
|
||||
if ( checkStreamForErrors('getNearEventsResponse', respObj) ) {
|
||||
return;
|
||||
}
|
||||
console.log(respObj);
|
||||
prevEventId = respObj.nearevents.PrevEventId;
|
||||
nextEventId = respObj.nearevents.NextEventId;
|
||||
prevEventStartTime = Date.parse(respObj.nearevents.PrevEventStartTime);
|
||||
|
@ -641,7 +642,7 @@ function getNearEventsResponse( respObj, respText ) {
|
|||
$j('#nextBtn').prop('disabled', nextEventId == 0 ? true : false).attr('class', nextEventId == 0 ? 'unavail' : 'inactive');
|
||||
}
|
||||
|
||||
function nearEventsQuery( eventId ) {
|
||||
function nearEventsQuery(eventId) {
|
||||
$j.getJSON(thisUrl + '?view=request&request=status&entity=nearevents&id='+eventId+filterQuery+sortQuery)
|
||||
.done(getNearEventsResponse)
|
||||
.fail(logAjaxFail);
|
||||
|
@ -839,7 +840,8 @@ function getStat() {
|
|||
});
|
||||
}
|
||||
|
||||
function onStatsResize(vidwidth) {
|
||||
function onStatsResize(vidWidth) {
|
||||
if (!vidWidth) return;
|
||||
var minWidth = 300; // An arbitrary value in pixels used to hide the stats table
|
||||
var scale = $j('#scale').val();
|
||||
|
||||
|
@ -847,8 +849,8 @@ function onStatsResize(vidwidth) {
|
|||
vidWidth = vidWidth * (scale/100);
|
||||
}
|
||||
|
||||
var width = $j(window).width() - vidwidth;
|
||||
//console.log("Width: " + width + " = window.width " + $j(window).width() + "- vidWidth" + vidwidth);
|
||||
var width = $j(window).width() - vidWidth;
|
||||
//console.log("Width: " + width + " = window.width " + $j(window).width() + "- vidWidth" + vidWidth);
|
||||
|
||||
// Hide the stats table if we have run out of room to show it properly
|
||||
if ( width < minWidth ) {
|
||||
|
|
|
@ -4,6 +4,9 @@ xhtmlHeaders(__FILE__, translate('Login'));
|
|||
<body>
|
||||
<?php echo getNavBarHTML(); ?>
|
||||
<div class="container">
|
||||
<?php
|
||||
if ( defined('ZM_OPT_USE_AUTH') and ZM_OPT_USE_AUTH ) {
|
||||
?>
|
||||
<form class="center-block" name="loginForm" id="loginForm" method="post" action="?">
|
||||
<input type="hidden" name="action" value="login"/>
|
||||
<input type="hidden" name="view" value="login"/>
|
||||
|
@ -34,6 +37,15 @@ if (
|
|||
} ?>
|
||||
<button class="btn btn-lg btn-primary btn-block" type="submit"><?php echo translate('Login') ?></button>
|
||||
</div>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<div class="error">
|
||||
User Authentication is not turned on. You cannot log in.
|
||||
</div>
|
||||
<?php
|
||||
} # end if ZM_OPT_AUTH
|
||||
?>
|
||||
</form>
|
||||
</div>
|
||||
<?php xhtmlFooter() ?>
|
||||
|
|
|
@ -43,20 +43,21 @@ if ( !empty($_REQUEST['mid']) ) {
|
|||
|
||||
if ( !$monitor ) {
|
||||
$nextId = getTableAutoInc('Monitors');
|
||||
if ( isset($_REQUEST['dupId']) ) {
|
||||
$monitor = new ZM\Monitor($_REQUEST['dupId']);
|
||||
$monitor->GroupIds(); // have to load before we change the Id
|
||||
if ( ZM_OPT_X10 )
|
||||
$x10Monitor = dbFetchOne('SELECT * FROM TriggersX10 WHERE MonitorId = ?', NULL, array($_REQUEST['dupId']));
|
||||
$clonedName = $monitor->Name();
|
||||
$monitor->Id(0);
|
||||
} else {
|
||||
$monitor = new ZM\Monitor();
|
||||
} # end if $_REQUEST['dupID']
|
||||
$monitor = new ZM\Monitor();
|
||||
$monitor->Name(translate('Monitor').'-'.$nextId);
|
||||
$monitor->WebColour(random_colour());
|
||||
} # end if $_REQUEST['mid']
|
||||
|
||||
if ( isset($_REQUEST['dupId']) ) {
|
||||
$monitor = new ZM\Monitor($_REQUEST['dupId']);
|
||||
$monitor->GroupIds(); // have to load before we change the Id
|
||||
if ( ZM_OPT_X10 )
|
||||
$x10Monitor = dbFetchOne('SELECT * FROM TriggersX10 WHERE MonitorId = ?', NULL, array($_REQUEST['dupId']));
|
||||
$clonedName = $monitor->Name();
|
||||
$monitor->Name('Clone of '.$monitor->Name());
|
||||
$monitor->Id(!empty($_REQUEST['mid'])?validInt($_REQUEST['mid']) : 0);
|
||||
}
|
||||
|
||||
if ( ZM_OPT_X10 && empty($x10Monitor) ) {
|
||||
$x10Monitor = array(
|
||||
'Activation' => '',
|
||||
|
@ -550,7 +551,7 @@ switch ( $name ) {
|
|||
<td class="text-right pr-3"><?php echo translate('LinkedMonitors'); echo makeHelpLink('OPTIONS_LINKED_MONITORS') ?></td>
|
||||
<td>
|
||||
<?php
|
||||
$monitors = dbFetchAll('SELECT Id, Name FROM Monitors ORDER BY Sequence ASC');
|
||||
$monitors = dbFetchAll('SELECT Id, Name FROM Monitors ORDER BY Name,Sequence ASC');
|
||||
$monitor_options = array();
|
||||
foreach ( $monitors as $linked_monitor ) {
|
||||
if ( (!$monitor->Id() || ($monitor->Id()!= $linked_monitor['Id'])) && visibleMonitor($linked_monitor['Id']) ) {
|
||||
|
|
|
@ -145,7 +145,6 @@ $tree = false;
|
|||
if ( isset($_REQUEST['filter']) ) {
|
||||
$filter = ZM\Filter::parse($_REQUEST['filter']);
|
||||
$tree = $filter->tree();
|
||||
ZM\Debug('Parse tree: ' . print_r($tree,true));
|
||||
}
|
||||
|
||||
if ( isset($_REQUEST['range']) )
|
||||
|
@ -196,9 +195,8 @@ if ( isset($minTime) && isset($maxTime) ) {
|
|||
$filterSql = parseTreeToSQL($tree);
|
||||
|
||||
if ( $filterSql ) {
|
||||
$filterSql = " AND $filterSql";
|
||||
$eventsSql .= $filterSql;
|
||||
$eventIdsSql .= $filterSql;
|
||||
$eventsSql .= ' AND '.$filterSql;
|
||||
$eventIdsSql .= ' AND '.$filterSql;
|
||||
}
|
||||
} else {
|
||||
$filterSql = parseTreeToSQL($tree);
|
||||
|
@ -206,10 +204,9 @@ if ( isset($minTime) && isset($maxTime) ) {
|
|||
extractDatetimeRange($tree, $tempMinTime, $tempMaxTime, $tempExpandable);
|
||||
|
||||
if ( $filterSql ) {
|
||||
$filterSql = " AND $filterSql";
|
||||
$rangeSql .= $filterSql;
|
||||
$eventsSql .= $filterSql;
|
||||
$eventIdsSql .= $filterSql;
|
||||
$rangeSql .= ' AND '.$filterSql;
|
||||
$eventsSql .= ' AND '.$filterSql;
|
||||
$eventIdsSql .= ' AND '.$filterSql;
|
||||
}
|
||||
|
||||
if ( !isset($minTime) || !isset($maxTime) ) {
|
||||
|
@ -220,8 +217,6 @@ if ( isset($minTime) && isset($maxTime) ) {
|
|||
$minTime = $row['MinTime'];
|
||||
if ( !isset($maxTime) )
|
||||
$maxTime = $row['MaxTime'];
|
||||
} else {
|
||||
# Errors will be reported by db functions
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,10 +232,9 @@ if ( isset($minTime) && isset($maxTime) ) {
|
|||
$range = ($maxTimeT - $minTimeT) + 1;
|
||||
$halfRange = (int)($range/2);
|
||||
$midTimeT = $minTimeT + $halfRange;
|
||||
$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT );
|
||||
$midTime = strftime(STRF_FMT_DATETIME_DB, $midTimeT);
|
||||
}
|
||||
|
||||
//echo "MnT: $tempMinTime, MxT: $tempMaxTime, ExP: $tempExpandable<br>";
|
||||
if ( $tree ) {
|
||||
appendDatetimeRange($tree, $minTime, $maxTime);
|
||||
|
||||
|
|
Loading…
Reference in New Issue