Merge branch 'storageareas' of github.com:ZoneMinder/ZoneMinder into storageareas

This commit is contained in:
Isaac Connor 2016-04-30 10:09:52 -04:00
commit 408fba8d24
115 changed files with 28012 additions and 27185 deletions

View File

@ -45,4 +45,4 @@ script:
- mysql -uzmuser -pzmpass < db/zm_create.sql - mysql -uzmuser -pzmpass < db/zm_create.sql
- mysql -uzmuser -pzmpass zm < db/test.monitor.sql - mysql -uzmuser -pzmpass zm < db/test.monitor.sql
- sudo zmpkg.pl start - sudo zmpkg.pl start
- sudo zmfilter.pl -f purgewhenfull - sudo zmfilter.pl --filter purgewhenfull

View File

@ -3,6 +3,19 @@
set -e set -e
if [ "$1" = "configure" ]; then if [ "$1" = "configure" ]; then
. /etc/zm/zm.conf
# 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
if [ "$ZM_DB_HOST" = "localhost" ]; then
if [ -e "/etc/init.d/mysql" ]; then if [ -e "/etc/init.d/mysql" ]; then
# #
# Get mysql started if it isn't # Get mysql started if it isn't
@ -15,39 +28,26 @@ if [ "$1" = "configure" ]; then
# test if database if already present... # test if database if already present...
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then 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 cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
echo 'grant lock tables, alter,select,insert,update,delete on zm.* to 'zmuser'@localhost identified by "zmpass";' | mysql --defaults-file=/etc/mysql/debian.cnf mysql # This creates the user.
echo "grant lock tables, alter,select,insert,update,delete,create,index 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,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi fi
# Ensure zoneminder is stopped
invoke-rc.d zoneminder stop || true invoke-rc.d zoneminder stop || true
zmupdate.pl --nointeractive zmupdate.pl --nointeractive
zmupdate.pl --nointeractive -f
invoke-rc.d zoneminder start || true
else else
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.' echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
fi fi
else else
echo 'mysql not found, assuming remote server.' echo 'mysql not found, assuming remote server.'
fi fi
chown www-data:www-data /var/log/zm
chown www-data:www-data /var/lib/zm/
if [ -z "$2" ]; then
chown www-data:www-data -R /var/cache/zoneminder
fi
fi
# Ensure zoneminder is stopped...
if [ -x "/etc/init.d/zoneminder" ]; then
if invoke-rc.d zoneminder status ; then
invoke-rc.d zoneminder stop || exit $?
fi
fi
if [ "$1" = "configure" ]; then
if [ -z "$2" ]; then
chown www-data:www-data /var/log/zm
chown www-data:www-data /var/lib/zm/
chown www-data:www-data -R /var/cache/zoneminder
else else
chown www-data:www-data /var/log/zm echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
zmupdate.pl
fi fi
fi fi
#DEBHELPER# #DEBHELPER#

View File

@ -1,3 +1,9 @@
zoneminder (1.30.2-trusty-2016042801) trusty; urgency=medium
* Merge video
-- Isaac Connor <iconnor@connortechnology.com> Thu, 28 Apr 2016 12:54:08 -0400
zoneminder (1.28.1+1-vivid-SNAPSHOT2015081701) vivid; urgency=medium zoneminder (1.28.1+1-vivid-SNAPSHOT2015081701) vivid; urgency=medium
* include api, switch to cmake build * include api, switch to cmake build

View File

@ -3,10 +3,50 @@
set -e set -e
if [ "$1" = "configure" ]; then if [ "$1" = "configure" ]; then
. /etc/zm/zm.conf
# 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:root /var/log/zm
chown www-data:www-data /var/lib/zm chown www-data:www-data /var/lib/zm
if [ -z "$2" ]; then if [ -z "$2" ]; then
chown www-data:www-data -R /var/cache/zoneminder chown www-data:www-data /var/cache/zoneminder /var/cache/zoneminder/*
fi
# Do this every time the package is installed or upgraded
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
# This creates the user.
echo "grant lock tables, alter,select,insert,update,delete,create,index 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,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi
# Ensure zoneminder is stopped
invoke-rc.d zoneminder stop || true
zmupdate.pl --nointeractive
zmupdate.pl --nointeractive -f
invoke-rc.d zoneminder start || true
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 fi
fi fi

View File

@ -1,3 +1,15 @@
zoneminder (1.30.2-trusty-2016033001) trusty; urgency=medium
* merge master
-- Isaac Connor <iconnor@connortechnology.com> Wed, 30 Mar 2016 14:09:48 -0400
zoneminder (1.30.2-trusty-2016032901) trusty; urgency=medium
* filter fixes, merge options rework by Kyle
-- Isaac Connor <iconnor@connortechnology.com> Tue, 29 Mar 2016 12:27:57 -0400
zoneminder (1.30.2-trusty-2016030702) trusty; urgency=medium zoneminder (1.30.2-trusty-2016030702) trusty; urgency=medium
* *

View File

@ -6,6 +6,7 @@ Uploaders: Vagrant Cascadian <vagrant@debian.org>
Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apache2-dev, dh-linktree Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apache2-dev, dh-linktree
,cmake ,cmake
,libavcodec-ffmpeg-dev, libavformat-ffmpeg-dev, libswscale-ffmpeg-dev, libavutil-ffmpeg-dev, libavdevice-ffmpeg-dev ,libavcodec-ffmpeg-dev, libavformat-ffmpeg-dev, libswscale-ffmpeg-dev, libavutil-ffmpeg-dev, libavdevice-ffmpeg-dev
,libx264-dev, libmp4v2-dev,
,libbz2-dev ,libbz2-dev
,libgcrypt-dev ,libgcrypt-dev
,libcurl4-gnutls-dev ,libcurl4-gnutls-dev
@ -34,10 +35,8 @@ Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,javascript-common ,javascript-common
,libav-tools ,libav-tools
,libdate-manip-perl ,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl
,libdbd-mysql-perl ,libdbd-mysql-perl
,libmime-lite-perl
,libmime-tools-perl
,libphp-serialization-perl ,libphp-serialization-perl
,libmodule-load-conditional-perl ,libmodule-load-conditional-perl
,libnet-sftp-foreign-perl ,libnet-sftp-foreign-perl
@ -57,12 +56,12 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,libsys-cpu-perl, libsys-meminfo-perl ,libsys-cpu-perl, libsys-meminfo-perl
,mysql-client | virtual-mysql-client ,mysql-client | virtual-mysql-client
,perl-modules ,perl-modules
,php5-mysql ,php5-mysql | php-mysql, php5-gd | php-gd
,policykit-1 ,policykit-1
,rsyslog | system-log-daemon ,rsyslog | system-log-daemon
,zip ,zip
Recommends: ${misc:Recommends} Recommends: ${misc:Recommends}
,libapache2-mod-php5 | php5-fpm ,libapache2-mod-php5 | libapache2-mod-php7 | php5-fpm
,mysql-server | virtual-mysql-server ,mysql-server | virtual-mysql-server
,zoneminder-doc (>= ${source:Version}) ,zoneminder-doc (>= ${source:Version})
Suggests: fcgiwrap, logrotate Suggests: fcgiwrap, logrotate

View File

@ -2,28 +2,57 @@
set -e set -e
. /etc/zm/zm.conf
if [ "$1" = "configure" ]; then if [ "$1" = "configure" ]; then
. /etc/zm/zm.conf
# 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:root /var/log/zm
chown www-data:www-data /var/lib/zm chown www-data:www-data /var/lib/zm
if [ -z "$2" ]; then if [ -z "$2" ]; then
chown www-data:www-data -R /var/cache/zoneminder chown www-data:www-data /var/cache/zoneminder /var/cache/zoneminder/*
fi fi
# Do this every time the package is installed or upgraded # Do this every time the package is installed or upgraded
# Test for database presence to avoid failure of zmupdate.pl
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
deb-systemd-invoke start mysql.service || exit $?
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
# This creates the user.
echo "grant lock tables,alter,select,insert,update,delete,create,index 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,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi
# Ensure zoneminder is stopped # Ensure zoneminder is stopped
deb-systemd-invoke stop zoneminder.service || exit $? deb-systemd-invoke stop zoneminder.service || exit $?
if [ "$ZM_DB_HOST" = "localhost" ]; then
echo 'grant lock tables, create, index, alter on zm.* to 'zmuser'@localhost identified by "zmpass";' | mysql --defaults-file=/etc/mysql/debian.cnf mysql
# Run the ZoneMinder update tool
zmupdate.pl --nointeractive zmupdate.pl --nointeractive
zmupdate.pl --nointeractive -f
deb-systemd-invoke start zoneminder.service || exit $?
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 else
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)" echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
fi; fi
fi fi

View File

@ -514,6 +514,8 @@ You do not need to rebuild ZM for X10 support. You will need to install the perl
Extending Zoneminder Extending Zoneminder
------------------------ ------------------------
.. _runstate_cron_example:
How can I get ZM to do different things at different times of day or week? How can I get ZM to do different things at different times of day or week?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -67,8 +67,14 @@ own empty screen.
* **D**: This is the core of ZoneMinder - recording events. It gives you a count of how many events were recorded over the hour, day, week, month. * **D**: This is the core of ZoneMinder - recording events. It gives you a count of how many events were recorded over the hour, day, week, month.
* **E**: These are the "Zones". Zones are areas within the camera that you mark as 'hotspots' for motion detection. Simply put, when you first configure your monitors (cameras), by default Zoneminder uses the entire field of view of the camera to detect motion. You may not want this. You may want to create "zones" specifically for detecting motion and ignore others. For example, lets consider a room with a fan that spins. You surely don't want to consider the fan moving continuously a reason for triggering a record? Probably not - in that case, you'd leave the fan out while making your zones. * **E**: These are the "Zones". Zones are areas within the camera that you mark as 'hotspots' for motion detection. Simply put, when you first configure your monitors (cameras), by default Zoneminder uses the entire field of view of the camera to detect motion. You may not want this. You may want to create "zones" specifically for detecting motion and ignore others. For example, lets consider a room with a fan that spins. You surely don't want to consider the fan moving continuously a reason for triggering a record? Probably not - in that case, you'd leave the fan out while making your zones.
* **F**: This is the "source" column that tells you the type of the camera - if its an IP camera, a USB camera or more. In this example, they are all IP cameras. Note the color red on item F ? Well that means there is something wrong with that camera. No wonder the log also shows red. Good indication for you to tap on logs and investigate * **F**: This is the "source" column that tells you the type of the camera - if its an IP camera, a USB camera or more. In this example, they are all IP cameras. Note the color red on item F ? Well that means there is something wrong with that camera. No wonder the log also shows red. Good indication for you to tap on logs and investigate
* **G**: This defines how Zoneminder will record events. There are various modes. In brief Modect == record if a motion is detected,Record = always record 24x7, Mocord = always record PLUS detect motion, Monitor = just provide a live view but don't record anytime, Nodect = Don't record till an externa entity via zmtrigger tells Zoneminder to (this is advanced usage). * **G**: This defines how Zoneminder will record events. There are various modes. In brief Modect == record if a motion is detected,Record = always record 24x7, Mocord = always record PLUS detect motion, Monitor = just provide a live view but don't record anytime, Nodect = Don't record till an external entity via zmtrigger tells Zoneminder to (this is advanced usage).
* **H**: If you click on these links you can view a "Montage" of all your configured monitors or cycle through each one * **H**: If you click on these links you can view a "Montage" of all your configured monitors or cycle through each one
* **I**: One of the most often missed features is the ability of ZoneMinder to maintain "run states". If you click on the "Running" text, ZoneMinder brings up a popup that allows you to define additional "states" (referred to as runstates). A runstate is essentially a snapshot that records the state of each monitor and you can switch between states easily. For example, you might have a run state defined that switches all monitors to "monitor" mode in which they are not recording anything while another state that sets some of the monitors to "modect". Why would you want this? A great example is to disable recording when you are at home and enable when you are away, based on time of day or other triggers. You can switch states by selecting an appropriate state manually, or do it automatically via cron jobs, for example. An example of using cron to automatically switch is provided in the :ref:`FAQ <runstate_cron_example>`. More esoteric examples of switching run states based on phone location can be found `here <https://forums.zoneminder.com/viewtopic.php?f=9&t=23026>`__.
Here is an example of multiple run states that I've defined. Each one of these runstates changes the mode of specific monitors depending on time of day and other conditions. Use your imagination to decide which conditions require state changes.
.. image:: images/runstates.png
Adding Monitors Adding Monitors

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -3825,6 +3825,41 @@ body = "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% s
readonly => 1, readonly => 1,
category => "dynamic", category => "dynamic",
}, },
{
name => "ZM_SSMTP_MAIL",
default => "no",
description => qqq("
Use a SSMTP mail server if available.
NEW_MAIL_MODULES must be enabled
"),
requires => [
{ name => "ZM_OPT_EMAIL", value => "yes" },
{ name => "ZM_OPT_MESSAGE", value => "yes" },
{ name => "ZM_NEW_MAIL_MODULES", value => "yes" }
],
help => qqq("
SSMTP is a lightweight and efficient method to send email.
The SSMTP application is not installed by default.
NEW_MAIL_MODULES must also be enabled.
Please visit: http://www.zoneminder.com/wiki/index.php/How_to_get_ssmtp_working_with_Zoneminder
for setup and configuration help.
"),
type => $types{boolean},
category => "mail",
},
{
name => "ZM_SSMTP_PATH",
default => "",
description => "SSMTP executable path",
requires => [{ name => "ZM_SSMTP_MAIL", value => "yes" }],
help => qqq("
Recommend setting the path to the SSMTP application.
If path is not defined. Zoneminder will try to determine
the path via shell command. Example path: /usr/sbin/ssmtp.
"),
type => $types{string},
category => "mail",
},
); );
our %options_hash = map { ( $_->{name}, $_ ) } @options; our %options_hash = map { ( $_->{name}, $_ ) } @options;

View File

@ -155,10 +155,12 @@ MAIN: while( $loop ) {
Fatal("ZM_AUDIT_MIN_AGE is not set in config."); Fatal("ZM_AUDIT_MIN_AGE is not set in config.");
} }
my %Monitors;
my $db_monitors; my $db_monitors;
my $monitorSelectSql = "select Id from Monitors order by Id"; my $monitorSelectSql = "select * from Monitors order by Id";
my $monitorSelectSth = $dbh->prepare_cached( $monitorSelectSql ) my $monitorSelectSth = $dbh->prepare_cached( $monitorSelectSql )
or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() );
my $eventSelectSql = "SELECT Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age my $eventSelectSql = "SELECT Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age
FROM Events WHERE MonitorId = ? ORDER BY Id"; FROM Events WHERE MonitorId = ? ORDER BY Id";
my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql ) my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql )
@ -169,6 +171,8 @@ MAIN: while( $loop ) {
or Fatal( "Can't execute: ".$monitorSelectSth->errstr() ); or Fatal( "Can't execute: ".$monitorSelectSth->errstr() );
while( my $monitor = $monitorSelectSth->fetchrow_hashref() ) while( my $monitor = $monitorSelectSth->fetchrow_hashref() )
{ {
$Monitors{$$monitor{Id}} = $monitor;
Debug( "Found database monitor '$monitor->{Id}'" ); Debug( "Found database monitor '$monitor->{Id}'" );
my $db_events = $db_monitors->{$monitor->{Id}} = {}; my $db_events = $db_monitors->{$monitor->{Id}} = {};
my $res = $eventSelectSth->execute( $monitor->{Id} ) my $res = $eventSelectSth->execute( $monitor->{Id} )
@ -467,20 +471,30 @@ MAIN: while( $loop ) {
# New audit to close any events that were left open for longer than MIN_AGE seconds # New audit to close any events that were left open for longer than MIN_AGE seconds
my $selectUnclosedEventsSql = my $selectUnclosedEventsSql =
"SELECT E.Id, #"SELECT E.Id, ANY_VALUE(E.MonitorId),
max(F.TimeStamp) as EndTime, #
unix_timestamp(max(F.TimeStamp)) - unix_timestamp(E.StartTime) as Length, #max(F.TimeStamp) as EndTime,
max(F.FrameId) as Frames, #unix_timestamp(max(F.TimeStamp)) - unix_timestamp(E.StartTime) as Length,
#max(F.FrameId) as Frames,
#count(if(F.Score>0,1,NULL)) as AlarmFrames,
#sum(F.Score) as TotScore,
#max(F.Score) as MaxScore
#FROM Events as E
#INNER JOIN Frames as F on E.Id = F.EventId
#WHERE isnull(E.Frames) or isnull(E.EndTime)
#GROUP BY E.Id HAVING EndTime < (now() - interval ".$Config{ZM_AUDIT_MIN_AGE}." second)"
#;
"SELECT *, unix_timestamp(StartTime) AS TimeStamp FROM Events WHERE EndTime IS NULL AND StartTime < (now() - interval ".$Config{ZM_AUDIT_MIN_AGE}." second)";
my $selectFrameDataSql = "SELECT max(TimeStamp) as EndTime, unix_timestamp(max(TimeStamp)) AS EndTimeStamp, max(FrameId) as Frames,
count(if(F.Score>0,1,NULL)) as AlarmFrames, count(if(F.Score>0,1,NULL)) as AlarmFrames,
sum(F.Score) as TotScore, sum(F.Score) as TotScore,
max(F.Score) as MaxScore, max(F.Score) as MaxScore
M.EventPrefix as Prefix FROM Frames WHERE EventId=?";
FROM Events as E my $selectFrameDataSth = $dbh->prepare_cached($selectFrameDataSql)
LEFT JOIN Monitors as M on E.MonitorId = M.Id or Fatal( "Can't prepare '$selectFrameDataSql': ".$dbh->errstr() );
INNER JOIN Frames as F on E.Id = F.EventId
WHERE isnull(E.Frames) or isnull(E.EndTime)
GROUP BY E.Id HAVING EndTime < (now() - interval ".$Config{ZM_AUDIT_MIN_AGE}." second)"
;
my $selectUnclosedEventsSth = $dbh->prepare_cached( $selectUnclosedEventsSql ) my $selectUnclosedEventsSth = $dbh->prepare_cached( $selectUnclosedEventsSql )
or Fatal( "Can't prepare '$selectUnclosedEventsSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$selectUnclosedEventsSql': ".$dbh->errstr() );
my $updateUnclosedEventsSql = my $updateUnclosedEventsSql =
@ -505,26 +519,32 @@ MAIN: while( $loop ) {
aud_print( "Found open event '$event->{Id}'" ); aud_print( "Found open event '$event->{Id}'" );
if ( confirm( 'close', 'closing' ) ) if ( confirm( 'close', 'closing' ) )
{ {
$res = $selectFrameDataSth->execute( $event->{Id} );
my $frame = $selectFrameDataSth->fetchrow_hashref();
if ( $frame ) {
$res = $updateUnclosedEventsSth->execute $res = $updateUnclosedEventsSth->execute
( (
sprintf("%s%d%s", sprintf("%s%d%s",
$event->{Prefix}, $Monitors{$event->{MonitorId}}->{EventPrefix},
$event->{Id}, $event->{Id},
RECOVER_TAG RECOVER_TAG
), ),
$event->{EndTime}, $frame->{EndTime},
$event->{Length}, $frame->{EndTimeStamp} - $event->{TimeStamp},
$event->{Frames}, $frame->{Frames},
$event->{AlarmFrames}, $frame->{AlarmFrames},
$event->{TotScore}, $frame->{TotScore},
$event->{AlarmFrames} $frame->{AlarmFrames}
? int($event->{TotScore} / $event->{AlarmFrames}) ? int($frame->{TotScore} / $frame->{AlarmFrames})
: 0 : 0
, ,
$event->{MaxScore}, $frame->{MaxScore},
RECOVER_TEXT, RECOVER_TEXT,
$event->{Id} $event->{Id}
) or Fatal( "Can't execute: ".$updateUnclosedEventsSth->errstr() ); ) or Fatal( "Can't execute: ".$updateUnclosedEventsSth->errstr() );
} else {
Error("SHOULD DELETE");
} # end if has frame data
} }
} }

View File

@ -862,7 +862,7 @@ sub killAll
my $killall; my $killall;
if ( '@HOST_OS@' eq 'BSD' ) if ( '@HOST_OS@' eq 'BSD' )
{ {
$killall = 'killall -'; $killall = 'killall -q -';
} elsif ( '@HOST_OS@' eq 'solaris' ) { } elsif ( '@HOST_OS@' eq 'solaris' ) {
$killall = 'pkill -'; $killall = 'pkill -';
} else { } else {

View File

@ -779,10 +779,32 @@ sub sendEmail
Disposition => "attachment" Disposition => "attachment"
); );
} }
### Send the Message if ( $Config{ZM_SSMTP_MAIL} ){
my $ssmtp_location = $Config{ZM_SSMTP_PATH};
if( ! $ssmtp_location ){
$ssmtp_location = qx('which ssmtp');
if ( logDebugging() )
{
Debug( "which ssmtp: $ssmtp_location - set ssmtp path in options to suppress this message\n" );
}
}
$mail->send( 'sendmail', $ssmtp_location, $Config{ZM_EMAIL_ADDRESS} );
}else{
MIME::Lite->send( "smtp", $Config{ZM_EMAIL_HOST}, Timeout=>60 ); MIME::Lite->send( "smtp", $Config{ZM_EMAIL_HOST}, Timeout=>60 );
$mail->send(); $mail->send();
} }
### Send the Message
#MIME::Lite->send( "smtp", $Config{ZM_EMAIL_HOST}, Timeout=>60 );
#$mail->send();
}
else else
{ {
my $mail = MIME::Entity->build( my $mail = MIME::Entity->build(

View File

@ -117,7 +117,8 @@ void zmLoadConfig()
Debug( 1, "Fetching ZM_SERVER_ID For Name = %s", staticConfig.SERVER_NAME.c_str() ); Debug( 1, "Fetching ZM_SERVER_ID For Name = %s", staticConfig.SERVER_NAME.c_str() );
std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() ); std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() );
if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) { zmDbRow dbrow;
if ( dbrow.fetch( sql.c_str() ) ) {
staticConfig.SERVER_ID = atoi(dbrow[0]); staticConfig.SERVER_ID = atoi(dbrow[0]);
} else { } else {
Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() ); Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() );
@ -128,7 +129,8 @@ void zmLoadConfig()
Debug( 1, "Fetching ZM_SERVER_NAME For Id = %d", staticConfig.SERVER_ID ); Debug( 1, "Fetching ZM_SERVER_NAME For Id = %d", staticConfig.SERVER_ID );
std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID ); std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID );
if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) { zmDbRow dbrow;
if ( dbrow.fetch( sql.c_str() ) ) {
staticConfig.SERVER_NAME = std::string(dbrow[0]); staticConfig.SERVER_NAME = std::string(dbrow[0]);
} else { } else {
Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID ); Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID );

View File

@ -95,19 +95,38 @@ MYSQL_RES * zmDbFetch( const char * query ) {
return result; return result;
} // end MYSQL_RES * zmDbFetch( const char * query ); } // end MYSQL_RES * zmDbFetch( const char * query );
MYSQL_ROW zmDbFetchOne( const char *query ) { zmDbRow *zmDbFetchOne( const char *query ) {
MYSQL_RES *result = zmDbFetch( query ); zmDbRow *row = new zmDbRow();
int n_rows = mysql_num_rows( result ); if ( row->fetch( query ) ) {
return row;
}
delete row;
return NULL;
}
MYSQL_RES *zmDbRow::fetch( const char *query ) {
result_set = zmDbFetch( query );
if ( ! result_set ) return result_set;
int n_rows = mysql_num_rows( result_set );
if ( n_rows != 1 ) { if ( n_rows != 1 ) {
Error( "Bogus number of lines return from query, %d returned for query %s.", n_rows, query ); Error( "Bogus number of lines return from query, %d returned for query %s.", n_rows, query );
return NULL; mysql_free_result( result_set );
result_set = NULL;
return result_set;
} }
MYSQL_ROW dbrow = mysql_fetch_row( result ); row = mysql_fetch_row( result_set );
mysql_free_result( result ); if ( ! row ) {
if ( ! dbrow ) { mysql_free_result( result_set );
result_set = NULL;
Error("Error getting row from query %s. Error is %s", query, mysql_error( &dbconn ) ); Error("Error getting row from query %s. Error is %s", query, mysql_error( &dbconn ) );
return NULL; } else {
Debug(3, "Succes");
} }
return dbrow; return result_set;
}
zmDbRow::~zmDbRow() {
if ( result_set )
mysql_free_result( result_set );
} }

View File

@ -22,6 +22,21 @@
#include <mysql/mysql.h> #include <mysql/mysql.h>
class zmDbRow {
private:
MYSQL_RES *result_set;
MYSQL_ROW row;
public:
zmDbRow() { result_set = NULL; row = NULL; };
MYSQL_RES *fetch( const char *query );
zmDbRow( MYSQL_RES *, MYSQL_ROW *row );
~zmDbRow();
char *operator[](unsigned int index) const {
return row[index];
}
};
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -33,7 +48,7 @@ void zmDbConnect();
void zmDbClose(); void zmDbClose();
MYSQL_RES * zmDbFetch( const char *query ); MYSQL_RES * zmDbFetch( const char *query );
MYSQL_ROW zmDbFetchOne( const char *query ); zmDbRow *zmDbFetchOne( const char *query );
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -840,7 +840,7 @@ bool EventStream::loadInitialEventData( int monitor_id, time_t event_time )
return( true ); return( true );
} }
bool EventStream::loadInitialEventData( int init_event_id, int init_frame_id ) bool EventStream::loadInitialEventData( int init_event_id, unsigned int init_frame_id )
{ {
loadEventData( init_event_id ); loadEventData( init_event_id );

View File

@ -49,23 +49,23 @@ class Monitor;
// //
class Event class Event
{ {
friend class EventStream; friend class EventStream;
protected: protected:
static bool initialised; static bool initialised;
static char capture_file_format[PATH_MAX]; static char capture_file_format[PATH_MAX];
static char analyse_file_format[PATH_MAX]; static char analyse_file_format[PATH_MAX];
static char general_file_format[PATH_MAX]; static char general_file_format[PATH_MAX];
static char video_file_format[PATH_MAX]; static char video_file_format[PATH_MAX];
protected: protected:
static int sd; static int sd;
public: public:
typedef std::set<std::string> StringSet; typedef std::set<std::string> StringSet;
typedef std::map<std::string,StringSet> StringSetMap; typedef std::map<std::string,StringSet> StringSetMap;
protected: protected:
typedef enum { NORMAL, BULK, ALARM } FrameType; typedef enum { NORMAL, BULK, ALARM } FrameType;
struct PreAlarmData struct PreAlarmData
@ -79,7 +79,7 @@ protected:
static int pre_alarm_count; static int pre_alarm_count;
static PreAlarmData pre_alarm_data[MAX_PRE_ALARM_FRAMES]; static PreAlarmData pre_alarm_data[MAX_PRE_ALARM_FRAMES];
protected: protected:
unsigned int id; unsigned int id;
Monitor *monitor; Monitor *monitor;
struct timeval start_time; struct timeval start_time;
@ -99,10 +99,10 @@ protected:
char timecodes_name[PATH_MAX]; char timecodes_name[PATH_MAX];
char timecodes_file[PATH_MAX]; char timecodes_file[PATH_MAX];
protected: protected:
int last_db_frame; int last_db_frame;
protected: protected:
static void Initialise() static void Initialise()
{ {
if ( initialised ) if ( initialised )
@ -118,11 +118,11 @@ protected:
void createNotes( std::string &notes ); void createNotes( std::string &notes );
public: public:
static bool OpenFrameSocket( int ); static bool OpenFrameSocket( int );
static bool ValidateFrameSocket( int ); static bool ValidateFrameSocket( int );
public: public:
Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap, bool p_videoEvent=false ); Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap, bool p_videoEvent=false );
~Event(); ~Event();
@ -144,10 +144,10 @@ public:
void AddFrames( int n_frames, Image **images, struct timeval **timestamps ); void AddFrames( int n_frames, Image **images, struct timeval **timestamps );
void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL ); void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL );
private: private:
void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps ); void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps );
public: public:
static const char *getSubPath( struct tm *time ) static const char *getSubPath( struct tm *time )
{ {
static char subpath[PATH_MAX] = ""; static char subpath[PATH_MAX] = "";
@ -163,7 +163,7 @@ public:
return video_file; return video_file;
} }
public: public:
static int PreAlarmCount() static int PreAlarmCount()
{ {
return( pre_alarm_count ); return( pre_alarm_count );
@ -204,10 +204,10 @@ public:
class EventStream : public StreamBase class EventStream : public StreamBase
{ {
public: public:
typedef enum { MODE_SINGLE, MODE_ALL, MODE_ALL_GAPLESS } StreamMode; typedef enum { MODE_SINGLE, MODE_ALL, MODE_ALL_GAPLESS } StreamMode;
protected: protected:
struct FrameData { struct FrameData {
//unsigned long id; //unsigned long id;
time_t timestamp; time_t timestamp;
@ -230,31 +230,31 @@ protected:
char video_file[PATH_MAX]; char video_file[PATH_MAX];
}; };
protected: protected:
static const int STREAM_PAUSE_WAIT = 250000; // Microseconds static const int STREAM_PAUSE_WAIT = 250000; // Microseconds
static const StreamMode DEFAULT_MODE = MODE_SINGLE; static const StreamMode DEFAULT_MODE = MODE_SINGLE;
protected: protected:
StreamMode mode; StreamMode mode;
bool forceEventChange; bool forceEventChange;
protected: protected:
int curr_frame_id; int curr_frame_id;
double curr_stream_time; double curr_stream_time;
EventData *event_data; EventData *event_data;
protected: protected:
bool loadEventData( int event_id ); bool loadEventData( int event_id );
bool loadInitialEventData( int init_event_id, int init_frame_id ); bool loadInitialEventData( int init_event_id, unsigned int init_frame_id );
bool loadInitialEventData( int monitor_id, time_t event_time ); bool loadInitialEventData( int monitor_id, time_t event_time );
void checkEventLoaded(); void checkEventLoaded();
void processCommand( const CmdMsg *msg ); void processCommand( const CmdMsg *msg );
bool sendFrame( int delta_us ); bool sendFrame( int delta_us );
public: public:
EventStream() EventStream()
{ {
mode = DEFAULT_MODE; mode = DEFAULT_MODE;
@ -266,7 +266,7 @@ public:
event_data = 0; event_data = 0;
} }
void setStreamStart( int init_event_id, int init_frame_id=0 ) void setStreamStart( int init_event_id, unsigned int init_frame_id=0 )
{ {
loadInitialEventData( init_event_id, init_frame_id ); loadInitialEventData( init_event_id, init_frame_id );
loadMonitor( event_data->monitor_id ); loadMonitor( event_data->monitor_id );

View File

@ -167,12 +167,21 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
#endif #endif
/* Check the buffer sizes */ /* 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,1);
#else
size_t insize = avpicture_get_size(in_pf, width, height); size_t insize = avpicture_get_size(in_pf, width, height);
#endif
if(insize != in_buffer_size) { 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); 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; return -4;
} }
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
size_t outsize = av_image_get_buffer_size(out_pf, width, height,1);
#else
size_t outsize = avpicture_get_size(out_pf, width, height); size_t outsize = avpicture_get_size(out_pf, width, height);
#endif
if(outsize < out_buffer_size) { if(outsize < out_buffer_size) {
Error("The output buffer is undersized for the output format. Required: %d Available: %d", outsize, out_buffer_size); Error("The output buffer is undersized for the output format. Required: %d Available: %d", outsize, out_buffer_size);
return -5; return -5;
@ -186,11 +195,27 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
} }
/* Fill in the buffers */ /* Fill in the buffers */
if(!avpicture_fill( (AVPicture*)input_avframe, (uint8_t*)in_buffer, in_pf, width, height ) ) { #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
if(av_image_fill_arrays(input_avframe->data, input_avframe->linesize,
(uint8_t*)in_buffer, in_pf, width, height, 1) <= 0)
{
#else
if(avpicture_fill( (AVPicture*)input_avframe, (uint8_t*)in_buffer,
in_pf, width, height ) <= 0)
{
#endif
Error("Failed filling input frame with input buffer"); Error("Failed filling input frame with input buffer");
return -7; return -7;
} }
if(!avpicture_fill( (AVPicture*)output_avframe, out_buffer, out_pf, width, height ) ) { #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
if(av_image_fill_arrays(output_avframe->data, output_avframe->linesize,
out_buffer, out_pf, width, height, 1) <= 0)
{
#else
if(avpicture_fill( (AVPicture*)output_avframe, out_buffer,
out_pf, width, height ) <= 0)
{
#endif
Error("Failed filling output frame with output buffer"); Error("Failed filling output frame with output buffer");
return -8; return -8;
} }
@ -338,15 +363,9 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
int flags = (is_output ? ic->oformat->flags : ic->iformat->flags); int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
AVStream *st = ic->streams[i]; AVStream *st = ic->streams[i];
AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
unsigned char *separator = ic->dump_separator; char separator = '\n';
char **codec_separator = (char **)av_opt_ptr(st->codec->av_class, st->codec, "dump_separator");
int use_format_separator = !*codec_separator;
if (use_format_separator)
*codec_separator = av_strdup((const char *)separator);
avcodec_string(buf, sizeof(buf), st->codec, is_output); avcodec_string(buf, sizeof(buf), st->codec, is_output);
if (use_format_separator)
av_freep(codec_separator);
Debug(3, " Stream #%d:%d", index, i); Debug(3, " Stream #%d:%d", index, i);
/* the pid is an important information, so we display it */ /* the pid is an important information, so we display it */

View File

@ -48,6 +48,12 @@ extern "C" {
#else #else
#include <libavcodec/opt.h> #include <libavcodec/opt.h>
#endif #endif
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
#include <libavutil/imgutils.h>
#else
#include <libavutil/avutil.h>
#endif
#elif HAVE_FFMPEG_AVUTIL_H #elif HAVE_FFMPEG_AVUTIL_H
#include <ffmpeg/avutil.h> #include <ffmpeg/avutil.h>
#include <ffmpeg/base64.h> #include <ffmpeg/base64.h>

View File

@ -61,6 +61,7 @@ FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::stri
mOpenStart = 0; mOpenStart = 0;
mReopenThread = 0; mReopenThread = 0;
wasRecording = false; wasRecording = false;
videoStore = NULL;
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
mConvertContext = NULL; mConvertContext = NULL;
@ -99,6 +100,7 @@ void FfmpegCamera::Initialise()
av_log_set_level( AV_LOG_QUIET ); av_log_set_level( AV_LOG_QUIET );
av_register_all(); av_register_all();
avformat_network_init();
} }
void FfmpegCamera::Terminate() void FfmpegCamera::Terminate()
@ -191,7 +193,13 @@ int FfmpegCamera::Capture( Image &image )
if ( frameComplete ) { if ( frameComplete ) {
Debug( 4, "Got frame %d", frameCount ); Debug( 4, "Got frame %d", frameCount );
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height); #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(mFrame->data, mFrame->linesize,
directbuffer, imagePixFormat, width, height, 1);
#else
avpicture_fill( (AVPicture *)mFrame, directbuffer,
imagePixFormat, width, height);
#endif
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
if(mConvertContext == NULL) { if(mConvertContext == NULL) {
@ -350,7 +358,8 @@ int FfmpegCamera::OpenFfmpeg() {
if ( mAudioStreamId == -1 ) if ( mAudioStreamId == -1 )
Debug( 2, "Unable to locate audio stream in %s", mPath.c_str() ); Debug( 2, "Unable to locate audio stream in %s", mPath.c_str() );
Debug ( 1, "Found video stream" ); Debug ( 3, "Found video stream at index %d", mVideoStreamId );
Debug ( 3, "Found audio stream at index %d", mAudioStreamId );
mCodecContext = mFormatContext->streams[mVideoStreamId]->codec; mCodecContext = mFormatContext->streams[mVideoStreamId]->codec;
@ -392,12 +401,17 @@ int FfmpegCamera::OpenFfmpeg() {
Debug ( 1, "Allocated frames" ); Debug ( 1, "Allocated frames" );
#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 ); int pSize = avpicture_get_size( imagePixFormat, width, height );
#endif
if( (unsigned int)pSize != imagesize) { if( (unsigned int)pSize != imagesize) {
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
} }
Debug ( 1, "Validated imagesize" ); Debug ( 1, "Validated imagesize %d", pSize );
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
Debug ( 1, "Calling sws_isSupportedInput" ); Debug ( 1, "Calling sws_isSupportedInput" );
@ -579,9 +593,11 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height); avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
//Keep the last keyframe so we can establish immediate video //Keep the last keyframe so we can establish immediate video
/*if(packet.flags & AV_PKT_FLAG_KEY) if(packet.flags & AV_PKT_FLAG_KEY) {
av_copy_packet(&lastKeyframePkt, &packet);*/ //Debug(4, "Have keyframe");
//av_copy_packet(&lastKeyframePkt, &packet);
//TODO I think we need to store the key frame location for seeking as part of the event //TODO I think we need to store the key frame location for seeking as part of the event
}
//Video recording //Video recording
if ( recording && !wasRecording ) { if ( recording && !wasRecording ) {
@ -592,6 +608,9 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
wasRecording = true; wasRecording = true;
strcpy(oldDirectory, event_file); strcpy(oldDirectory, event_file);
// Need to write out all the frames from the last keyframe?
} else if ( ( ! recording ) && wasRecording && videoStore ) { } else if ( ( ! recording ) && wasRecording && videoStore ) {
Info("Deleting videoStore instance"); Info("Deleting videoStore instance");
delete videoStore; delete videoStore;
@ -649,9 +668,10 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
} }
if ( videoStore && recording ) { if ( videoStore && recording ) {
if ( record_audio ) { if ( record_audio ) {
Debug(3, "Recording audio packet" ); Debug(3, "Recording audio packet streamindex(%d) packetstreamindex(%d)", mAudioStreamId, packet.stream_index );
//Write the packet to our video store //Write the packet to our video store
int ret = videoStore->writeAudioFramePacket(&packet, mFormatContext->streams[packet.stream_index]); //FIXME no relevance of last key frame //FIXME no relevance of last key frame
int ret = videoStore->writeAudioFramePacket( &packet, mFormatContext->streams[packet.stream_index] );
if ( ret < 0 ) {//Less than zero and we skipped a frame if ( ret < 0 ) {//Less than zero and we skipped a frame
av_free_packet( &packet ); av_free_packet( &packet );
return 0; return 0;
@ -661,7 +681,11 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
} }
} }
} else { } else {
#if LIBAVUTIL_VERSION_CHECK(54, 23, 0, 23, 0)
Debug( 3, "Some other stream index %d, %s", packet.stream_index, av_get_media_type_string( mFormatContext->streams[packet.stream_index]->codec->codec_type) ); Debug( 3, "Some other stream index %d, %s", packet.stream_index, av_get_media_type_string( mFormatContext->streams[packet.stream_index]->codec->codec_type) );
#else
Debug( 3, "Some other stream index %d", packet.stream_index );
#endif
} }
av_free_packet( &packet ); av_free_packet( &packet );
} // end while ! frameComplete } // end while ! frameComplete

View File

@ -64,7 +64,9 @@ protected:
bool wasRecording; bool wasRecording;
VideoStore *videoStore; VideoStore *videoStore;
char oldDirectory[4096]; char oldDirectory[4096];
//AVPacket lastKeyframePkt;
// Last Key frame
AVPacket lastKeyframePkt;
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
struct SwsContext *mConvertContext; struct SwsContext *mConvertContext;

View File

@ -644,7 +644,11 @@ LocalCamera::LocalCamera(
if ( !tmpPicture ) if ( !tmpPicture )
Fatal( "Could not allocate temporary picture" ); Fatal( "Could not allocate temporary picture" );
#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 ); int pSize = avpicture_get_size( imagePixFormat, width, height );
#endif
if( (unsigned int)pSize != imagesize) { if( (unsigned int)pSize != imagesize) {
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
} }
@ -877,7 +881,18 @@ void LocalCamera::Initialise()
#endif #endif
if ( !capturePictures[i] ) if ( !capturePictures[i] )
Fatal( "Could not allocate picture" ); Fatal( "Could not allocate picture" );
avpicture_fill( (AVPicture *)capturePictures[i], (uint8_t*)v4l2_data.buffers[i].start, capturePixFormat, v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height ); #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(capturePictures[i]->data,
capturePictures[i]->linesize,
(uint8_t*)v4l2_data.buffers[i].start,capturePixFormat,
v4l2_data.fmt.fmt.pix.width,
v4l2_data.fmt.fmt.pix.height, 1);
#else
avpicture_fill( (AVPicture *)capturePictures[i],
(uint8_t*)v4l2_data.buffers[i].start, capturePixFormat,
v4l2_data.fmt.fmt.pix.width,
v4l2_data.fmt.fmt.pix.height );
#endif
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE
} }
@ -1035,7 +1050,16 @@ void LocalCamera::Initialise()
#endif #endif
if ( !capturePictures[i] ) if ( !capturePictures[i] )
Fatal( "Could not allocate picture" ); Fatal( "Could not allocate picture" );
avpicture_fill( (AVPicture *)capturePictures[i], (unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i], capturePixFormat, width, height ); #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(capturePictures[i]->data,
capturePictures[i]->linesize,
(unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i],
capturePixFormat, width, height, 1);
#else
avpicture_fill( (AVPicture *)capturePictures[i],
(unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i],
capturePixFormat, width, height );
#endif
} }
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE
@ -2131,7 +2155,14 @@ int LocalCamera::Capture( Image &image )
Debug( 9, "Calling sws_scale to perform the conversion" ); Debug( 9, "Calling sws_scale to perform the conversion" );
/* Use swscale to convert the image directly into the shared memory */ /* Use swscale to convert the image directly into the shared memory */
avpicture_fill( (AVPicture *)tmpPicture, directbuffer, imagePixFormat, width, height ); #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(tmpPicture->data,
tmpPicture->linesize, directbuffer,
imagePixFormat, width, height, 1);
#else
avpicture_fill( (AVPicture *)tmpPicture, directbuffer,
imagePixFormat, width, height );
#endif
sws_scale( imgConversionContext, capturePictures[capture_frame]->data, capturePictures[capture_frame]->linesize, 0, height, tmpPicture->data, tmpPicture->linesize ); sws_scale( imgConversionContext, capturePictures[capture_frame]->data, capturePictures[capture_frame]->linesize, 0, height, tmpPicture->data, tmpPicture->linesize );
} }
#endif #endif

View File

@ -615,7 +615,7 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
{ {
int priority = smSyslogPriorities[level]; int priority = smSyslogPriorities[level];
//priority |= LOG_DAEMON; //priority |= LOG_DAEMON;
syslog( priority, "%s [%s]", classString, syslogStart ); syslog( priority, "%s [%s] [%s]", classString, mId.c_str(), syslogStart );
} }
if ( level <= FATAL ) if ( level <= FATAL )

View File

@ -1119,13 +1119,13 @@ void Monitor::DumpZoneImage( const char *zone_string ) {
Debug(3, "Trying to load from event"); Debug(3, "Trying to load from event");
// Grab the most revent event image // Grab the most revent event image
std::string sql = stringtf( "SELECT MAX(Id) FROM Events WHERE MonitorId=%d AND Frames > 0", id ); std::string sql = stringtf( "SELECT MAX(Id) FROM Events WHERE MonitorId=%d AND Frames > 0", id );
MYSQL_ROW eventid_row = zmDbFetchOne(sql.c_str() ); zmDbRow eventid_row;
if ( eventid_row ) { if ( eventid_row.fetch( sql.c_str() ) ) {
int event_id = atoi( eventid_row[0] ); int event_id = atoi( eventid_row[0] );
Debug( 3, "Got event %d", event_id ); Debug( 3, "Got event %d", event_id );
EventStream *stream = new EventStream(); EventStream *stream = new EventStream();
stream->setStreamStart( event_id, 1 ); stream->setStreamStart( event_id, (unsigned int)1 );
zone_image = stream->getImage(); zone_image = stream->getImage();
} else { } else {
Error("Unable to load an event for monitor %d", id ); Error("Unable to load an event for monitor %d", id );
@ -1279,6 +1279,7 @@ bool Monitor::Analyse()
{ {
if ( shared_data->last_read_index == shared_data->last_write_index ) if ( shared_data->last_read_index == shared_data->last_write_index )
{ {
// I wonder how often this happens. Maybe if this happens we should sleep or something?
return( false ); return( false );
} }
@ -1299,8 +1300,10 @@ bool Monitor::Analyse()
if ( read_margin < 0 ) read_margin += image_buffer_count; if ( read_margin < 0 ) read_margin += image_buffer_count;
int step = 1; int step = 1;
// Isn't read_margin always > 0 here?
if ( read_margin > 0 ) if ( read_margin > 0 )
{ {
// TODO explain this so... 90% of image buffer / 50% of read margin?
step = (9*image_buffer_count)/(5*read_margin); step = (9*image_buffer_count)/(5*read_margin);
} }
@ -1380,6 +1383,7 @@ bool Monitor::Analyse()
if ( static_undef ) if ( static_undef )
{ {
// Sure would be nice to be able to assume that these were already initialized. It's just 1 compare/branch, but really not neccessary.
static_undef = false; static_undef = false;
timestamps = new struct timeval *[pre_event_count]; timestamps = new struct timeval *[pre_event_count];
images = new Image *[pre_event_count]; images = new Image *[pre_event_count];
@ -1392,6 +1396,7 @@ bool Monitor::Analyse()
bool signal_change = (signal != last_signal); bool signal_change = (signal != last_signal);
//Set video recording flag for event start constructor and easy reference in code //Set video recording flag for event start constructor and easy reference in code
// TODO: Use enum instead of the # 2. Makes for easier reading
bool videoRecording = ((GetOptVideoWriter() == 2) && camera->SupportsNativeVideo()); bool videoRecording = ((GetOptVideoWriter() == 2) && camera->SupportsNativeVideo());
if ( trigger_data->trigger_state != TRIGGER_OFF ) if ( trigger_data->trigger_state != TRIGGER_OFF )
@ -2177,9 +2182,6 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose
col++; col++;
bool embed_exif = (*dbrow[col] != '0'); col++; bool embed_exif = (*dbrow[col] != '0'); col++;
int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width);
int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height);
int extras = (deinterlacing>>24)&0xff; int extras = (deinterlacing>>24)&0xff;
Camera *camera = new LocalCamera( Camera *camera = new LocalCamera(
@ -2190,8 +2192,8 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose
v4l_multi_buffer, v4l_multi_buffer,
v4l_captures_per_frame, v4l_captures_per_frame,
method, method,
cam_width, width,
cam_height, height,
colours, colours,
palette, palette,
brightness, brightness,
@ -2344,9 +2346,6 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
int track_motion = atoi(dbrow[col]); col++; int track_motion = atoi(dbrow[col]); col++;
bool embed_exif = (*dbrow[col] != '0'); col++; bool embed_exif = (*dbrow[col] != '0'); col++;
int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width);
int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height);
Camera *camera = 0; Camera *camera = 0;
if ( protocol == "http" ) { if ( protocol == "http" ) {
camera = new RemoteCameraHttp( camera = new RemoteCameraHttp(
@ -2355,8 +2354,8 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
host, // Host host, // Host
port, // Port port, // Port
path, // Path path, // Path
cam_width, width,
cam_height, height,
colours, colours,
brightness, brightness,
contrast, contrast,
@ -2374,8 +2373,8 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
host, // Host host, // Host
port, // Port port, // Port
path, // Path path, // Path
cam_width, width,
cam_height, height,
rtsp_describe, rtsp_describe,
colours, colours,
brightness, brightness,
@ -2526,14 +2525,11 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
int track_motion = atoi(dbrow[col]); col++; int track_motion = atoi(dbrow[col]); col++;
bool embed_exif = (*dbrow[col] != '0'); col++; bool embed_exif = (*dbrow[col] != '0'); col++;
int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width);
int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height);
Camera *camera = new FileCamera( Camera *camera = new FileCamera(
id, id,
path, // File path, // File
cam_width, width,
cam_height, height,
colours, colours,
brightness, brightness,
contrast, contrast,
@ -2683,16 +2679,13 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
int track_motion = atoi(dbrow[col]); col++; int track_motion = atoi(dbrow[col]); col++;
bool embed_exif = (*dbrow[col] != '0'); col++; bool embed_exif = (*dbrow[col] != '0'); col++;
int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width);
int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height);
Camera *camera = new FfmpegCamera( Camera *camera = new FfmpegCamera(
id, id,
path, // File path, // File
method, method,
options, options,
cam_width, width,
cam_height, height,
colours, colours,
brightness, brightness,
contrast, contrast,
@ -2765,8 +2758,8 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) { Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
std::string sql = stringtf( "select Id, Name, ServerId, StorageId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", p_id ); std::string sql = stringtf( "select Id, Name, ServerId, StorageId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", p_id );
MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ); zmDbRow dbrow;
if ( ! dbrow ) { if ( ! dbrow.fetch( sql.c_str() ) ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) ); Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
} }
@ -2864,9 +2857,6 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
col++; col++;
bool embed_exif = (*dbrow[col] != '0'); col++; bool embed_exif = (*dbrow[col] != '0'); col++;
int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width);
int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height);
int extras = (deinterlacing>>24)&0xff; int extras = (deinterlacing>>24)&0xff;
Camera *camera = 0; Camera *camera = 0;
@ -2880,8 +2870,8 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
v4l_multi_buffer, v4l_multi_buffer,
v4l_captures_per_frame, v4l_captures_per_frame,
method, method,
cam_width, width,
cam_height, height,
colours, colours,
palette, palette,
brightness, brightness,
@ -2903,8 +2893,8 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
host.c_str(), host.c_str(),
port.c_str(), port.c_str(),
path.c_str(), path.c_str(),
cam_width, width,
cam_height, height,
colours, colours,
brightness, brightness,
contrast, contrast,
@ -2921,8 +2911,8 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
host.c_str(), host.c_str(),
port.c_str(), port.c_str(),
path.c_str(), path.c_str(),
cam_width, width,
cam_height, height,
rtsp_describe, rtsp_describe,
colours, colours,
brightness, brightness,
@ -2942,8 +2932,8 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
camera = new FileCamera( camera = new FileCamera(
id, id,
path.c_str(), path.c_str(),
cam_width, width,
cam_height, height,
colours, colours,
brightness, brightness,
contrast, contrast,
@ -2959,8 +2949,8 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
path.c_str(), path.c_str(),
method, method,
options, options,
cam_width, width,
cam_height, height,
colours, colours,
brightness, brightness,
contrast, contrast,
@ -2979,8 +2969,8 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
path.c_str(), path.c_str(),
method, method,
options, options,
cam_width, width,
cam_height, height,
colours, colours,
brightness, brightness,
contrast, contrast,
@ -2999,8 +2989,8 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
path.c_str(), path.c_str(),
user.c_str(), user.c_str(),
pass.c_str(), pass.c_str(),
cam_width, width,
cam_height, height,
colours, colours,
brightness, brightness,
contrast, contrast,
@ -3281,191 +3271,6 @@ bool Monitor::closeEvent()
return( false ); return( false );
} }
//-----------------------------------------
/*
* NOTE Nextime's comment:
*
* OurCheckAlarms seems to be called only by DetectBlack method, and DetectBlack
* method is only called in a commented line instead of DetectMotion in zm_monitor.cpp.
*
* Probably this is just a dead code used for debugghing purpose, so, instead of fixing it
* it seems to be safe to just comment it out.
*
* Anyway, the issues with this code is that it assumes the image to be an RGB24 image,
* so, as i've discussed on IRC with mastertheknife, changes needed are:
*
* Check if the image is 24 or 32 bits ( pImage->Colours() says 3 for 24 and 4 for 32 bits,
* comparing it with ZM_COLOUR_RGB24 or ZM_COLOUR_RGB32 is the way ), and then
* manage che check using RGB_VAL_RED() and so on macros instead of just RED().
*
* Be careful that in 32 bit images we need to check also where the alpha channel is, so,
* (RGBA and BGRA) or (ABGR and ARGB) aren't the same!
*
* To check black pixels in 32 bit images i can do a more efficient way using
* RGBA_ZERO_ALPHA(pixel) == RGBA_ZERO_ALPHA(RGB_BLACK), but before of that i need to
* check where the alpha channel is and maybe convert it.
* Maybe this won't work as they assign "23" to black_thr, so, they are not checking
* if the pixel is black, but just "quasi" black is enough.
*
* Anyway, for the moment, comment out whole part.
*/
/*
bool Monitor::OurCheckAlarms( Zone *zone, const Image *pImage )
{
Info("Entering OurCheckAlarms >>>>>>>>>>>>>>>>>>>>>>>>>>>>");
unsigned char black_thr = 23;
int min_alarm_score = 10;
int max_alarm_score = 99;
//bool alarm = false;
unsigned int score;
Polygon zone_polygon = zone->GetPolygon();
Info("Got polygon of a zone. It has %d vertices.", zone_polygon.getNumCoords());
zone->ResetStats();
Info("ResetStats done.");
if ( !zone->CheckOverloadCount() )
{
Info("CheckOverloadCount() return false, we'll return false.");
return( false );
}
Image *pMaskImage = new Image(pImage->Width(), pImage->Height(), ZM_COLOUR_GRAY8, pImage->SubpixelOrder());
Info("Mask image created.");
pMaskImage->Fill(BLACK);
Info("Mask image filled with BLACK.");
if (pImage->Colours() == ZM_COLOUR_GRAY8)
{
Info("Analysed image is not colored! Set score = 0.");
score = 0;
}
else
{
Info("Start processing image.");
//Process image
unsigned char *buffer = (unsigned char*)pImage->Buffer();
unsigned char *mask_buffer = (unsigned char*)pMaskImage->Buffer();
int black_pixels_count = 0;
Info("Loop for black pixels counting and mask filling.");
while (buffer < (pImage->Buffer() + pImage->Size()))
{
if ( (RED(buffer) < black_thr) && (GREEN(buffer) < black_thr) && (BLUE(buffer) < black_thr) )
{
*mask_buffer = WHITE;
black_pixels_count++;
}
buffer += pImage->Colours();
mask_buffer++;
}
if ( !black_pixels_count )
{
delete pMaskImage;
return( false );
}
score = (100*black_pixels_count)/zone_polygon.Area();
Info("Number of black pixels is %d, zone polygon area is %d, score is %d", black_pixels_count, zone_polygon.Area(), score);
if ( min_alarm_score && ( score < min_alarm_score) )
{
delete pMaskImage;
return( false );
}
if ( max_alarm_score && (score > max_alarm_score) )
{
zone->SetOverloadCount(zone->GetOverloadFrames());
delete pMaskImage;
return( false );
}
}
zone->SetScore(score);
Info("Score have been set in zone.");
//Get mask
Rgb alarm_colour = RGB_RED;
Image *tempImage = pMaskImage->HighlightEdges(alarm_colour, &zone_polygon.Extent() );
Info("After HighlightEdges");
zone->SetAlarmImage(tempImage);
Info("After SetAlarmImage");
delete pMaskImage;
Info("After Delete pMaskImage");
delete tempImage;
Info("Leaving OurCheckAlarms >>>>>>>>>>>>>>>>>>>>>>>>>>>>");
return true;
}
unsigned int Monitor::DetectBlack(const Image &comp_image, Event::StringSet &zoneSet )
{
Info("Entering DetectBlack >>>>>>>>>>>>>>>>>>>>>>>>>>");
bool alarm = false;
unsigned int score = 0;
if ( n_zones <= 0 ) return( alarm );
// Coord alarm_centre;
// int top_score = -1;
// Find all alarm pixels in active zones
Info("Number of zones to process %d", n_zones);
for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
{
Zone *zone = zones[n_zone];
if ( !zone->IsActive() )
{
continue;
}
Debug( 3, "Checking active zone %s", zone->Label() );
Info( "Checking active zone %s", zone->Label() );
if ( OurCheckAlarms( zone, &comp_image ) )
{
Info("OurCheckAlarm is TRUE!!!!!!");
alarm = true;
score += zone->Score();
zone->SetAlarm();
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
Info( "Zone is alarmed, zone score = %d", zone->Score() );
zoneSet.insert( zone->Label() );
// if ( config.opt_control && track_motion )
// {
// if ( (int)zone->Score() > top_score )
// {
// top_score = zone->Score();
// alarm_centre = zone->GetAlarmCentre();
// }
// }
}
Info( "Finish checking active zone %s", zone->Label() );
}
// if ( top_score > 0 )
// {
// shared_data->alarm_x = alarm_centre.X();
// shared_data->alarm_y = alarm_centre.Y();
//
// Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, image_count );
// }
// else
// {
// shared_data->alarm_x = shared_data->alarm_y = -1;
// }
// This is a small and innocent hack to prevent scores of 0 being returned in alarm state
Info("Leaving DetectBlack <<<<<<<<<<<<<<<<<<<<<<<<<<<");
return( score?score:alarm );
}
*/
//-----------------------------------------------------------------------------------------------
unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ) unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &zoneSet )
{ {
bool alarm = false; bool alarm = false;

View File

@ -48,9 +48,9 @@
// //
class Monitor class Monitor
{ {
friend class MonitorStream; friend class MonitorStream;
public: public:
typedef enum typedef enum
{ {
QUERY=0, QUERY=0,
@ -87,7 +87,7 @@ public:
TAPE TAPE
} State; } State;
protected: protected:
typedef std::set<Zone *> ZoneSet; typedef std::set<Zone *> ZoneSet;
typedef enum { GET_SETTINGS=0x1, SET_SETTINGS=0x2, RELOAD=0x4, SUSPEND=0x10, RESUME=0x20 } Action; typedef enum { GET_SETTINGS=0x1, SET_SETTINGS=0x2, RELOAD=0x4, SUSPEND=0x10, RESUME=0x20 } Action;
@ -218,7 +218,7 @@ protected:
bool hasAlarmed(); bool hasAlarmed();
}; };
protected: protected:
// These are read from the DB and thereafter remain unchanged // These are read from the DB and thereafter remain unchanged
unsigned int id; unsigned int id;
char name[64]; char name[64];
@ -325,9 +325,9 @@ protected:
int n_linked_monitors; int n_linked_monitors;
MonitorLink **linked_monitors; MonitorLink **linked_monitors;
public: public:
// OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info. // OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info.
//bool OurCheckAlarms( Zone *zone, const Image *pImage ); //bool OurCheckAlarms( Zone *zone, const Image *pImage );
Monitor( Monitor(
int p_id, int p_id,
const char *p_name, const char *p_name,
@ -417,8 +417,8 @@ public:
return( embed_exif ); return( embed_exif );
} }
unsigned int Width() const { return( width ); } unsigned int Width() const { return width; }
unsigned int Height() const { return( height ); } unsigned int Height() const { return height; }
unsigned int Colours() const { return( camera->Colours() ); } unsigned int Colours() const { return( camera->Colours() ); }
unsigned int SubpixelOrder() const { return( camera->SubpixelOrder() ); } unsigned int SubpixelOrder() const { return( camera->SubpixelOrder() ); }
@ -505,36 +505,36 @@ public:
#define MOD_ADD( var, delta, limit ) (((var)+(limit)+(delta))%(limit)) #define MOD_ADD( var, delta, limit ) (((var)+(limit)+(delta))%(limit))
class MonitorStream : public StreamBase { class MonitorStream : public StreamBase {
protected: protected:
typedef struct SwapImage { typedef struct SwapImage {
bool valid; bool valid;
struct timeval timestamp; struct timeval timestamp;
char file_name[PATH_MAX]; char file_name[PATH_MAX];
} SwapImage; } SwapImage;
private: private:
SwapImage *temp_image_buffer; SwapImage *temp_image_buffer;
int temp_image_buffer_count; int temp_image_buffer_count;
int temp_read_index; int temp_read_index;
int temp_write_index; int temp_write_index;
protected: protected:
time_t ttl; time_t ttl;
protected: protected:
int playback_buffer; int playback_buffer;
bool delayed; bool delayed;
int frame_count; int frame_count;
protected: protected:
bool checkSwapPath( const char *path, bool create_path ); bool checkSwapPath( const char *path, bool create_path );
bool sendFrame( const char *filepath, struct timeval *timestamp ); bool sendFrame( const char *filepath, struct timeval *timestamp );
bool sendFrame( Image *image, struct timeval *timestamp ); bool sendFrame( Image *image, struct timeval *timestamp );
void processCommand( const CmdMsg *msg ); void processCommand( const CmdMsg *msg );
public: public:
MonitorStream() : playback_buffer( 0 ), delayed( false ), frame_count( 0 ) { MonitorStream() : playback_buffer( 0 ), delayed( false ), frame_count( 0 ) {
} }
void setStreamBuffer( int p_playback_buffer ) { void setStreamBuffer( int p_playback_buffer ) {

View File

@ -333,7 +333,13 @@ void VideoStream::OpenStream( )
Panic( "Could not allocate opicture" ); Panic( "Could not allocate opicture" );
} }
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
int size = av_image_get_buffer_size( c->pix_fmt, c->width,
c->height, 1 );
#else
int size = avpicture_get_size( c->pix_fmt, c->width, c->height ); int size = avpicture_get_size( c->pix_fmt, c->width, c->height );
#endif
uint8_t *opicture_buf = (uint8_t *)av_malloc( size ); uint8_t *opicture_buf = (uint8_t *)av_malloc( size );
if ( !opicture_buf ) if ( !opicture_buf )
{ {
@ -344,7 +350,13 @@ void VideoStream::OpenStream( )
#endif #endif
Panic( "Could not allocate opicture_buf" ); Panic( "Could not allocate opicture_buf" );
} }
avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt, c->width, c->height ); #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(opicture->data, opicture->linesize,
opicture_buf, c->pix_fmt, c->width, c->height, 1);
#else
avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt,
c->width, c->height );
#endif
/* if the output format is not identical to the input format, then a temporary /* if the output format is not identical to the input format, then a temporary
picture is needed too. It is then converted to the required picture is needed too. It is then converted to the required
@ -361,7 +373,12 @@ void VideoStream::OpenStream( )
{ {
Panic( "Could not allocate tmp_opicture" ); Panic( "Could not allocate tmp_opicture" );
} }
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
int size = av_image_get_buffer_size( pf, c->width,
c->height,1 );
#else
int size = avpicture_get_size( pf, c->width, c->height ); int size = avpicture_get_size( pf, c->width, c->height );
#endif
uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc( size ); uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc( size );
if ( !tmp_opicture_buf ) if ( !tmp_opicture_buf )
{ {
@ -372,7 +389,14 @@ void VideoStream::OpenStream( )
#endif #endif
Panic( "Could not allocate tmp_opicture_buf" ); Panic( "Could not allocate tmp_opicture_buf" );
} }
avpicture_fill( (AVPicture *)tmp_opicture, tmp_opicture_buf, pf, c->width, c->height ); #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(tmp_opicture->data,
tmp_opicture->linesize, tmp_opicture_buf, pf,
c->width, c->height, 1);
#else
avpicture_fill( (AVPicture *)tmp_opicture,
tmp_opicture_buf, pf, c->width, c->height );
#endif
} }
} }
@ -678,14 +702,14 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
#endif #endif
if ( got_packet ) if ( got_packet )
{ {
if ( c->coded_frame->key_frame ) // if ( c->coded_frame->key_frame )
{ // {
#if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2) //#if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2)
pkt->flags |= AV_PKT_FLAG_KEY; // pkt->flags |= AV_PKT_FLAG_KEY;
#else //#else
pkt->flags |= PKT_FLAG_KEY; // pkt->flags |= PKT_FLAG_KEY;
#endif //#endif
} // }
if ( pkt->pts != (int64_t)AV_NOPTS_VALUE ) if ( pkt->pts != (int64_t)AV_NOPTS_VALUE )
{ {

View File

@ -241,7 +241,12 @@ int RemoteCameraRtsp::PrimeCapture()
if(mRawFrame == NULL || mFrame == NULL) if(mRawFrame == NULL || mFrame == NULL)
Fatal( "Unable to allocate frame(s)"); Fatal( "Unable to allocate frame(s)");
#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 ); int pSize = avpicture_get_size( imagePixFormat, width, height );
#endif
if( (unsigned int)pSize != imagesize) { if( (unsigned int)pSize != imagesize) {
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
} }
@ -299,24 +304,6 @@ int RemoteCameraRtsp::Capture( Image &image ) {
if ( !buffer.size() ) if ( !buffer.size() )
return( -1 ); return( -1 );
int avResult = av_read_frame( mFormatContext, &packet );
if ( avResult < 0 ) {
char errbuf[AV_ERROR_MAX_STRING_SIZE];
av_strerror(avResult, errbuf, AV_ERROR_MAX_STRING_SIZE);
if (
// Check if EOF.
(avResult == AVERROR_EOF || (mFormatContext->pb && mFormatContext->pb->eof_reached)) ||
// Check for Connection failure.
(avResult == -110)
) {
Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf);
//ReopenFfmpeg();
}
Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, avResult, errbuf );
return( -1 );
}
if(mCodecContext->codec_id == AV_CODEC_ID_H264) { if(mCodecContext->codec_id == AV_CODEC_ID_H264) {
// SPS and PPS frames should be saved and appended to IDR frames // SPS and PPS frames should be saved and appended to IDR frames
int nalType = (buffer.head()[3] & 0x1f); int nalType = (buffer.head()[3] & 0x1f);
@ -339,6 +326,8 @@ int avResult = av_read_frame( mFormatContext, &packet );
buffer += lastSps; buffer += lastSps;
buffer += lastPps; buffer += lastPps;
} }
} else {
Debug(3, "Not an h264 packet");
} }
av_init_packet( &packet ); av_init_packet( &packet );
@ -498,7 +487,13 @@ int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* even
Debug( 3, "Got frame %d", frameCount ); Debug( 3, "Got frame %d", frameCount );
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height ); #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(mFrame->data, mFrame->linesize,
directbuffer, imagePixFormat, width, height, 1);
#else
avpicture_fill( (AVPicture *)mFrame, directbuffer,
imagePixFormat, width, height);
#endif
//Video recording //Video recording
if ( recording && !wasRecording ) { if ( recording && !wasRecording ) {

View File

@ -47,15 +47,12 @@ RETSIGTYPE zm_die_handler(int signal, siginfo_t * info, void *context)
RETSIGTYPE zm_die_handler(int signal) RETSIGTYPE zm_die_handler(int signal)
#endif #endif
{ {
#if (defined(__i386__) || defined(__x86_64__))
void *cr2 = 0;
void *ip = 0;
#endif
Error("Got signal %d (%s), crashing", signal, strsignal(signal)); Error("Got signal %d (%s), crashing", signal, strsignal(signal));
#if (defined(__i386__) || defined(__x86_64__)) #if (defined(__i386__) || defined(__x86_64__))
// Get more information if available // Get more information if available
#if ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) #if ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T )
void *ip = 0;
void *cr2 = 0;
if (info && context) { if (info && context) {
Debug(1, Debug(1,
@ -65,19 +62,19 @@ RETSIGTYPE zm_die_handler(int signal)
ucontext_t *uc = (ucontext_t *) context; ucontext_t *uc = (ucontext_t *) context;
cr2 = info->si_addr; cr2 = info->si_addr;
#if defined(__x86_64__) #if defined(__x86_64__)
#ifdef __FreeBSD_kernel__ #ifdef __FreeBSD_kernel__
ip = (void *)(uc->uc_mcontext.mc_rip); ip = (void *)(uc->uc_mcontext.mc_rip);
#else #else
ip = (void *)(uc->uc_mcontext.gregs[REG_RIP]); ip = (void *)(uc->uc_mcontext.gregs[REG_RIP]);
#endif #endif
#else #else
#ifdef __FreeBSD_kernel__ #ifdef __FreeBSD_kernel__
ip = (void *)(uc->uc_mcontext.mc_eip); ip = (void *)(uc->uc_mcontext.mc_eip);
#else #else
ip = (void *)(uc->uc_mcontext.gregs[REG_EIP]); ip = (void *)(uc->uc_mcontext.gregs[REG_EIP]);
#endif #endif
#endif // defined(__x86_64__) #endif // defined(__x86_64__)
// Print the signal address and instruction pointer if available // Print the signal address and instruction pointer if available
if (ip) { if (ip) {
@ -86,11 +83,11 @@ RETSIGTYPE zm_die_handler(int signal)
Error("Signal address is %p, no instruction pointer", cr2); Error("Signal address is %p, no instruction pointer", cr2);
} }
} }
#endif // ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) #endif // ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T )
// Print backtrace if enabled and available // Print backtrace if enabled and available
#if ( !defined(ZM_NO_CRASHTRACE) && HAVE_DECL_BACKTRACE && HAVE_DECL_BACKTRACE_SYMBOLS ) #if ( !defined(ZM_NO_CRASHTRACE) && HAVE_DECL_BACKTRACE && HAVE_DECL_BACKTRACE_SYMBOLS )
void *trace[TRACE_SIZE]; void *trace[TRACE_SIZE];
int trace_size = 0; int trace_size = 0;
trace_size = backtrace(trace, TRACE_SIZE); trace_size = backtrace(trace, TRACE_SIZE);
@ -111,7 +108,7 @@ RETSIGTYPE zm_die_handler(int signal)
Info("Backtrace complete, please execute the following command for more information"); Info("Backtrace complete, please execute the following command for more information");
Info(cmd); Info(cmd);
#endif // ( !defined(ZM_NO_CRASHTRACE) && HAVE_DECL_BACKTRACE && HAVE_DECL_BACKTRACE_SYMBOLS ) #endif // ( !defined(ZM_NO_CRASHTRACE) && HAVE_DECL_BACKTRACE && HAVE_DECL_BACKTRACE_SYMBOLS )
#endif // (defined(__i386__) || defined(__x86_64__) #endif // (defined(__i386__) || defined(__x86_64__)
exit(signal); exit(signal);
} }

View File

@ -50,8 +50,8 @@ Storage::Storage( unsigned int p_id ) {
char sql[ZM_SQL_SML_BUFSIZ]; char sql[ZM_SQL_SML_BUFSIZ];
snprintf( sql, sizeof(sql), "SELECT Id, Name, Path from Storage WHERE Id=%d", p_id ); snprintf( sql, sizeof(sql), "SELECT Id, Name, Path from Storage WHERE Id=%d", p_id );
Debug(1,"Loading Storage for %d using %s", p_id, sql ); Debug(1,"Loading Storage for %d using %s", p_id, sql );
MYSQL_ROW dbrow = zmDbFetchOne( sql ); zmDbRow dbrow;
if ( ! dbrow ) { if ( ! dbrow.fetch( sql ) ) {
Error( "Unable to load storage area for id %d: %s", p_id, mysql_error( &dbconn ) ); Error( "Unable to load storage area for id %d: %s", p_id, mysql_error( &dbconn ) );
} else { } else {
unsigned int index = 0; unsigned int index = 0;

View File

@ -253,7 +253,7 @@ void *Thread::mThreadFunc( void *arg )
Debug( 2, "Invoking thread" ); Debug( 2, "Invoking thread" );
Thread *thisPtr = (Thread *)arg; Thread *thisPtr = (Thread *)arg;
void *status = 0; thisPtr->status = 0;
try try
{ {
thisPtr->mThreadMutex.lock(); thisPtr->mThreadMutex.lock();
@ -261,19 +261,18 @@ void *Thread::mThreadFunc( void *arg )
thisPtr->mThreadCondition.signal(); thisPtr->mThreadCondition.signal();
thisPtr->mThreadMutex.unlock(); thisPtr->mThreadMutex.unlock();
thisPtr->mRunning = true; thisPtr->mRunning = true;
int run=(thisPtr->run()); thisPtr->status = thisPtr->run();
status = (void *)&run;
thisPtr->mRunning = false; thisPtr->mRunning = false;
Debug( 2, "Exiting thread, status %p", status ); Debug( 2, "Exiting thread, status %p", (void *)&(thisPtr->status) );
return (void *)&(thisPtr->status);
} }
catch ( const ThreadException &e ) catch ( const ThreadException &e )
{ {
Error( "%s", e.getMessage().c_str() ); Error( "%s", e.getMessage().c_str() );
thisPtr->mRunning = false; thisPtr->mRunning = false;
status = (void *)-1; Debug( 2, "Exiting thread after exception, status %p", (void *)-1 );
Debug( 2, "Exiting thread after exception, status %p", status ); return (void *)-1;
} }
return( status );
} }
void Thread::start() void Thread::start()

View File

@ -36,7 +36,7 @@ class ThreadException : public Exception
{ {
private: private:
#ifndef SOLARIS #ifndef SOLARIS
pid_t pid() { pid_t pid() {
pid_t tid; pid_t tid;
#ifdef __FreeBSD__ #ifdef __FreeBSD__
long lwpid; long lwpid;
@ -50,9 +50,9 @@ pid_t pid() {
#endif #endif
#endif #endif
return tid; return tid;
} }
#else #else
pthread_t pid() { return( pthread_self() ); } pthread_t pid() { return( pthread_self() ); }
#endif #endif
public: public:
ThreadException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)pid() ) ) { ThreadException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)pid() ) ) {
@ -224,6 +224,7 @@ protected:
#endif #endif
bool mStarted; bool mStarted;
bool mRunning; bool mRunning;
int status; // Used in various funcions to get around return a local variable
protected: protected:
Thread(); Thread();
@ -253,10 +254,10 @@ return tid;
return( pthread_self() ); return( pthread_self() );
} }
#endif #endif
void exit( int status = 0 ) void exit( int p_status = 0 )
{ {
//INFO( "Exiting" ); //INFO( "Exiting" );
pthread_exit( (void *)&status ); pthread_exit( (void *)&p_status );
} }
static void *mThreadFunc( void *arg ); static void *mThreadFunc( void *arg );

View File

@ -29,11 +29,12 @@
#include "zm_videostore.h" #include "zm_videostore.h"
extern "C"{ extern "C"{
#include "libavutil/time.h" #include "libavutil/time.h"
} }
VideoStore::VideoStore(const char *filename_in, const char *format_in, VideoStore::VideoStore(const char *filename_in, const char *format_in,
AVStream *input_st, AVStream *inpaud_st, AVStream *input_st,
AVStream *inpaud_st,
int64_t nStartTime) { int64_t nStartTime) {
AVDictionary *pmetadata = NULL; AVDictionary *pmetadata = NULL;
@ -46,14 +47,20 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
keyframeMessage = false; keyframeMessage = false;
keyframeSkipNumber = 0; keyframeSkipNumber = 0;
Info("Opening video storage stream %s format: %d\n", filename, format);
Info("Opening video storage stream %s\n", filename);
//Init everything we need //Init everything we need
int ret; int ret;
av_register_all(); av_register_all();
avformat_alloc_output_context2(&oc, NULL, NULL, filename); ret = avformat_alloc_output_context2(&oc, NULL, NULL, filename);
if ( ret < 0 ) {
Warning("Could not create video storage stream %s as no output context"
" could be assigned based on filename: %s",
filename,
av_make_error_string(ret).c_str()
);
}
//Couldn't deduce format from filename, trying from format name //Couldn't deduce format from filename, trying from format name
if (!oc) { if (!oc) {
@ -72,15 +79,15 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
fmt = oc->oformat; fmt = oc->oformat;
video_st = avformat_new_stream(oc, input_st->codec->codec); video_st = avformat_new_stream(oc, (AVCodec *)input_st->codec->codec);
if (!video_st) { if (!video_st) {
Fatal("Unable to create video out stream\n"); Fatal("Unable to create video out stream\n");
} }
ret = avcodec_copy_context(video_st->codec, input_st->codec); ret = avcodec_copy_context(video_st->codec, input_st->codec);
if (ret < 0) { if (ret < 0) {
Fatal("Unable to copy input video context to output video context " Fatal("Unable to copy input video context to output video context %s\n",
"%s\n", av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
} }
video_st->codec->codec_tag = 0; video_st->codec->codec_tag = 0;
@ -89,19 +96,27 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
} }
if (inpaud_st) { if (inpaud_st) {
audio_st = avformat_new_stream(oc, inpaud_st->codec->codec);
audio_st = avformat_new_stream(oc, (AVCodec *)inpaud_st->codec->codec);
if (!audio_st) { if (!audio_st) {
Fatal("Unable to create audio out stream\n"); Error("Unable to create audio out stream\n");
} audio_st = NULL;
ret=avcodec_copy_context(audio_st->codec, inpaud_st->codec); } else {
ret = avcodec_copy_context(audio_st->codec, inpaud_st->codec);
if (ret < 0) { if (ret < 0) {
Fatal("Unable to copy audio context %s\n", av_make_error_string(ret).c_str()); Fatal("Unable to copy audio context %s\n", av_make_error_string(ret).c_str());
} }
audio_st->codec->codec_tag = 0; audio_st->codec->codec_tag = 0;
if ( audio_st->codec->channels > 1 ) {
Warning("Audio isn't mono, changing it.");
audio_st->codec->channels = 1;
}
if (oc->oformat->flags & AVFMT_GLOBALHEADER) { if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
audio_st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; audio_st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
} }
}
} else { } else {
Debug(3, "No Audio output stream");
audio_st = NULL; audio_st = NULL;
} }
@ -114,11 +129,19 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
} }
} }
//av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
//if ((ret = avformat_write_header(ctx, &opts)) < 0) {
//}
//os->ctx_inited = 1;
//avio_flush(ctx->pb);
//av_dict_free(&opts);
/* Write the stream header, if any. */ /* Write the stream header, if any. */
ret = avformat_write_header(oc, NULL); ret = avformat_write_header(oc, NULL);
if (ret < 0) { if (ret < 0) {
Fatal("Error occurred when writing output file header: %s\n", zm_dump_stream_format( oc, 0, 0, 1 );
Fatal("Error occurred when writing output file header to %s: %s\n",
filename,
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
} }
@ -129,7 +152,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
startTime=av_gettime()-nStartTime;//oc->start_time; startTime=av_gettime()-nStartTime;//oc->start_time;
Info("VideoStore startTime=%d\n",startTime); Info("VideoStore startTime=%d\n",startTime);
} } // VideoStore::VideoStore
VideoStore::~VideoStore(){ VideoStore::~VideoStore(){
@ -140,16 +163,24 @@ VideoStore::~VideoStore(){
Debug(3, "Sucess Writing trailer"); Debug(3, "Sucess Writing trailer");
} }
// I wonder if we should be closing the file first.
// I also wonder if we really need to be doing all the context allocation/de-allocation constantly, or whether we can just re-use it. Just do a file open/close/writeheader/etc.
// What if we were only doing audio recording?
if ( video_st ) {
avcodec_close(video_st->codec); avcodec_close(video_st->codec);
}
if (audio_st) { if (audio_st) {
avcodec_close(audio_st->codec); avcodec_close(audio_st->codec);
} }
// WHen will be not using a file ?
if (!(fmt->flags & AVFMT_NOFILE)) { if (!(fmt->flags & AVFMT_NOFILE)) {
/* Close the output file. */ /* Close the output file. */
if ( int rc= avio_close(oc->pb) ) { if ( int rc = avio_close(oc->pb) ) {
Error("Error closing avio %s", av_err2str( rc ) ); Error("Error closing avio %s", av_err2str( rc ) );
} }
} else {
Debug(3, "Not closing avio because we are not writing to a file.");
} }
/* free the stream */ /* free the stream */
@ -247,34 +278,47 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_st){//, AV
int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_st){ int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_st){
if(!audio_st) if(!audio_st) {
Error("Called writeAudioFramePacket when no audio_st");
return -1;//FIXME -ve return codes do not free packet in ffmpeg_camera at the moment return -1;//FIXME -ve return codes do not free packet in ffmpeg_camera at the moment
}
/*if(!keyframeMessage) /*if(!keyframeMessage)
return -1;*/ return -1;*/
//zm_dump_stream_format( oc, ipkt->stream_index, 0, 1 );
int64_t ost_tb_start_time = av_rescale_q(startTime, AV_TIME_BASE_Q, video_st->time_base); // What is this doing? Getting the time of the start of this video chunk? Does that actually make sense?
int64_t ost_tb_start_time = av_rescale_q(startTime, AV_TIME_BASE_Q, audio_st->time_base);
AVPacket opkt; AVPacket opkt;
av_init_packet(&opkt); av_init_packet(&opkt);
Debug(3, "after init packet" );
//Scale the PTS of the outgoing packet to be the correct time base //Scale the PTS of the outgoing packet to be the correct time base
if (ipkt->pts != AV_NOPTS_VALUE) if (ipkt->pts != AV_NOPTS_VALUE) {
Debug(3, "Rescaling output pts");
opkt.pts = av_rescale_q(ipkt->pts-startPts, input_st->time_base, audio_st->time_base) - ost_tb_start_time; opkt.pts = av_rescale_q(ipkt->pts-startPts, input_st->time_base, audio_st->time_base) - ost_tb_start_time;
else } else {
Debug(3, "Setting output pts to AV_NOPTS_VALUE");
opkt.pts = AV_NOPTS_VALUE; opkt.pts = AV_NOPTS_VALUE;
}
//Scale the DTS of the outgoing packet to be the correct time base //Scale the DTS of the outgoing packet to be the correct time base
if(ipkt->dts == AV_NOPTS_VALUE) { if(ipkt->dts == AV_NOPTS_VALUE) {
Debug(4, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
opkt.dts = av_rescale_q(input_st->cur_dts-startDts, AV_TIME_BASE_Q, audio_st->time_base); opkt.dts = av_rescale_q(input_st->cur_dts-startDts, AV_TIME_BASE_Q, audio_st->time_base);
Debug(3, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts ); Debug(4, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
} else } else {
Debug(4, "ipkt->dts != AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
opkt.dts = av_rescale_q(ipkt->dts-startDts, input_st->time_base, audio_st->time_base); opkt.dts = av_rescale_q(ipkt->dts-startDts, input_st->time_base, audio_st->time_base);
Debug(4, "ipkt->dts != AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
}
opkt.dts -= ost_tb_start_time; opkt.dts -= ost_tb_start_time;
// Seems like it would be really weird for the codec type to NOT be audiu
if (audio_st->codec->codec_type == AVMEDIA_TYPE_AUDIO && ipkt->dts != AV_NOPTS_VALUE) { if (audio_st->codec->codec_type == AVMEDIA_TYPE_AUDIO && ipkt->dts != AV_NOPTS_VALUE) {
Debug( 3, "code is audio, dts != AV_NOPTS_VALUE " ); Debug( 4, "code is audio, dts != AV_NOPTS_VALUE " );
int duration = av_get_audio_frame_duration(input_st->codec, ipkt->size); int duration = av_get_audio_frame_duration(input_st->codec, ipkt->size);
if(!duration) if(!duration)
duration = input_st->codec->frame_size; duration = input_st->codec->frame_size;
@ -299,7 +343,7 @@ Debug(3, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
if(ret!=0){ if(ret!=0){
Fatal("Error encoding audio frame packet: %s\n", av_make_error_string(ret).c_str()); Fatal("Error encoding audio frame packet: %s\n", av_make_error_string(ret).c_str());
} }
Debug(4,"Success writing audio frame" );
av_free_packet(&opkt); av_free_packet(&opkt);
return 0; return 0;
} }

View File

@ -62,7 +62,7 @@ int main( int argc, const char *argv[] )
int monitor_id = 0; int monitor_id = 0;
time_t event_time = 0; time_t event_time = 0;
int event_id = 0; int event_id = 0;
int frame_id = 1; unsigned int frame_id = 1;
unsigned int scale = 100; unsigned int scale = 100;
unsigned int rate = 100; unsigned int rate = 100;
double maxfps = 10.0; double maxfps = 10.0;

252
src/zmstreamer.cpp Normal file
View File

@ -0,0 +1,252 @@
//
// ZoneMinder Streamer, $Date: 2010-10-14 23:21:00 +0200 (Thu, 14 Oct 2010) $
// Copyright (C) 2001-2010 Philip Coombes, Chris Kistner
//
// This program is based on revision 3143 of
// http://svn.zoneminder.com/svn/zm/trunk/src/zms.cpp
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/*
=head1 NAME
zmstreamer - eyeZM video streamer
=head1 SYNOPSIS
zmstreamer -e <mode>
zmstreamer -o <format>
zmstreamer -u <buffer size>
zmstreamer -f <maximum fps>
zmstreamer -s <scale>
zmstreamer -b <bitrate in bps>
zmstreamer -m <monitor id>
zmstreamer -d <debug mode>
zmstreamer -i
zmstreamer -?
zmstreamer -h
zmstreamer -v
=head1 DESCRIPTION
*DEPRECIATED* The xml skin and all files associated with the xml skin are now
depreciated. Please use the ZoneMinder API instead.
This binary works in conjunction with the XML skin to stream video to iPhones
running the eyeZm app.
=head1 OPTIONS
-e <mode> - Specify output mode: mpeg/jpg/zip/single/raw.
-o <format> - Specify output format.
-u <buffer size> - Specify buffer size in ms.
-f <maximum fps> - Specify maximum framerate.
-s <scale> - Specify scale.
-b <bitrate in bps> - Specify bitrate.
-m <monitor id> - Specify monitor id.
-d <debug mode> - 0 = off, 1 = no streaming, 2 = with streaming.
-i, -?, -h - Display usage information
-v - Print the installed version of ZoneMinder
=cut
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "zm.h"
#include "zm_db.h"
#include "zm_user.h"
#include "zm_signal.h"
#include "zm_monitor.h"
#include "zm_stream.h"
// Possible command-line options
#define OPTIONS "e:o:u:f:s:b:m:d:i:?:h:v"
// Default ZMS values
#define ZMS_DEFAULT_DEBUG 0
#define ZMS_DEFAULT_ID 1
#define ZMS_DEFAULT_BITRATE 100000
#define ZMS_DEFAULT_SCALE 100
#define ZMS_DEFAULT_MODE "mpeg"
#define ZMS_DEFAULT_FORMAT "asf"
#define ZMS_DEFAULT_FPS 25.0
#define ZMS_DEFAULT_BUFFER 1000
int main(int argc, char** argv) {
self = argv[0];
// Set initial values to the default values
int debug = ZMS_DEFAULT_DEBUG;
int id = ZMS_DEFAULT_ID;
int bitrate = ZMS_DEFAULT_BITRATE;
int scale = ZMS_DEFAULT_SCALE;
char mode[32];
sprintf(mode, "%s", ZMS_DEFAULT_MODE);
char format[32];
sprintf(format, "%s", ZMS_DEFAULT_FORMAT);
double maxfps = ZMS_DEFAULT_FPS;
int buffer = ZMS_DEFAULT_BUFFER;
// Parse command-line options
int arg;
while ((arg = getopt(argc, argv, OPTIONS)) != -1) {
switch (arg) {
case 'e':
sprintf(mode, "%s", optarg);
break;
case 'o':
sprintf(format, "%s", optarg);
break;
case 'u':
buffer = atoi(optarg);
break;
case 'f':
maxfps = atof(optarg);
break;
case 's':
scale = atoi(optarg);
break;
case 'b':
bitrate = atoi(optarg);
break;
case 'm':
id = atoi(optarg);
break;
case 'd':
debug = atoi(optarg);
break;
case 'h':
case 'i':
case '?':
printf("-e <mode> : Specify output mode: mpeg/jpg/zip/single/raw. Default = %s\n", ZMS_DEFAULT_MODE);
printf("-o <format> : Specify output format. Default = %s\n", ZMS_DEFAULT_FORMAT);
printf("-u <buffer size> : Specify buffer size in ms. Default = %d\n", ZMS_DEFAULT_BUFFER);
printf("-f <maximum fps> : Specify maximum framerate. Default = %lf\n", ZMS_DEFAULT_FPS);
printf("-s <scale> : Specify scale. Default = %d\n", ZMS_DEFAULT_SCALE);
printf("-b <bitrate in bps> : Specify bitrate. Default = %d\n", ZMS_DEFAULT_BITRATE);
printf("-m <monitor id> : Specify monitor id. Default = %d\n", ZMS_DEFAULT_ID);
printf("-d <debug mode> : 0 = off, 1 = no streaming, 2 = with streaming. Default = 0\n");
printf("-i or -? or -h: This information\n");
printf("-v : This installed version of ZoneMinder\n");
return EXIT_SUCCESS;
case 'v':
std::cout << ZM_VERSION << "\n";
exit(0);
}
}
// Set stream type
StreamBase::StreamType streamtype;
if (!strcasecmp("raw", mode))
streamtype = MonitorStream::STREAM_RAW;
else if (!strcasecmp("mpeg", mode))
streamtype = MonitorStream::STREAM_MPEG;
else if (!strcasecmp("jpg", mode))
streamtype = MonitorStream::STREAM_JPEG;
else if (!strcasecmp("single", mode))
streamtype = MonitorStream::STREAM_SINGLE;
else if (!strcasecmp("zip", mode))
streamtype = MonitorStream::STREAM_ZIP;
else
streamtype = MonitorStream::STREAM_MPEG;
if (debug) {
// Show stream parameters
printf("Stream parameters:\n");
switch (streamtype) {
case MonitorStream::STREAM_MPEG:
printf("Output mode (-e) = %s\n", "mpeg");
printf("Output format (-o) = %s\n", format);
break;
default:
printf("Output mode (-e) = %s\n", mode);
}
printf("Buffer size (-u) = %d ms\n", buffer);
printf("Maximum FPS (-f) = %lf FPS\n", maxfps);
printf("Scale (-s) = %d%%\n", scale);
printf("Bitrate (-b) = %d bps\n", bitrate);
printf("Monitor Id (-m) = %d\n", id);
}
if (debug) {
// Set ZM debugger to print to stdout
printf("Setting up ZoneMinder debugger to print to stdout...");
setenv("ZM_DBG_PRINT", "1", 1);
printf("Done.\n");
}
// Loading ZM configurations
printf("Loading ZoneMinder configurations...");
zmLoadConfig();
printf("Done.\n");
logInit("zmstreamer");
ssedetect();
// Setting stream parameters
MonitorStream stream;
stream.setStreamScale(scale); // default = 100 (scale)
stream.setStreamReplayRate(100); // default = 100 (rate)
stream.setStreamMaxFPS(maxfps); // default = 10 (maxfps)
if (debug) stream.setStreamTTL(1);
else stream.setStreamTTL(0); // default = 0 (ttl)
stream.setStreamQueue(0); // default = 0 (connkey)
stream.setStreamBuffer(buffer); // default = 0 (buffer)
stream.setStreamStart(id); // default = 0 (monitor_id)
stream.setStreamType(streamtype);
if (streamtype == MonitorStream::STREAM_MPEG) {
#if HAVE_LIBAVCODEC
if (debug) printf("HAVE_LIBAVCODEC is set\n");
stream.setStreamFormat(format); // default = "" (format)
stream.setStreamBitrate(bitrate); // default = 100000 (bitrate)
#else
fprintf(stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n");
logTerm();
zmDbClose();
return EXIT_FAILURE;
#endif
}
if (debug != 1) {
if (debug) printf("Running stream...");
// Output headers
fprintf(stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION);
time_t now = time(0);
char date_string[64];
strftime(date_string, sizeof (date_string) - 1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
fprintf(stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n");
fprintf(stdout, "Last-Modified: %s\r\n", date_string);
fprintf(stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n");
fprintf(stdout, "Cache-Control: post-check=0, pre-check=0\r\n");
fprintf(stdout, "Pragma: no-cache\r\n");
// Run stream
stream.runStream();
}
if (debug) printf("Done.\n");
logTerm();
zmDbClose();
return (EXIT_SUCCESS);
}

View File

@ -756,15 +756,14 @@ int main( int argc, char *argv[] )
if ( function & ZMU_LIST ) if ( function & ZMU_LIST )
{ {
char sql[ZM_SQL_SML_BUFSIZ]; std::string sql = "select Id, Function+0 from Monitors";
strncpy( sql, "select Id, Function+0 from Monitors", sizeof(sql) );
if ( !verbose ) if ( !verbose )
{ {
strncat( sql, " where Function != 'None'", sizeof(sql)-strlen(sql) ); sql += "where Function != 'None'";
} }
strncat( sql, " order by Id asc", sizeof(sql)-strlen(sql) ); sql += " order by Id asc";
if ( mysql_query( &dbconn, sql ) ) if ( mysql_query( &dbconn, sql.c_str() ) )
{ {
Error( "Can't run query: %s", mysql_error( &dbconn ) ); Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );

76
web/includes/Frame.php Normal file
View File

@ -0,0 +1,76 @@
<?php
require_once( 'database.php' );
require_once( 'Event.php' );
class Frame {
public function __construct( $IdOrRow ) {
$row = NULL;
if ( $IdOrRow ) {
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT * FROM Frames WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) {
Error("Unable to load Frame record for Id=" . $IdOrRow );
}
} elseif ( is_array( $IdOrRow ) ) {
$row = $IdOrRow;
} else {
Error("Unknown argument passed to Frame Constructor ($IdOrRow)");
return;
}
} # end if isset($IdOrRow)
if ( $row ) {
foreach ($row as $k => $v) {
$this->{$k} = $v;
}
} else {
Error("No row for Frame " . $IdOrRow );
}
} // end function __construct
public function Storage() {
return $this->Event()->Storage();
}
public function Event() {
return new Event( $this->{'EventId'} );
}
public function __call( $fn, array $args){
if(isset($this->{$fn})){
return $this->{$fn};
#array_unshift($args, $this);
#call_user_func_array( $this->{$fn}, $args);
}
}
public function Path() {
$Storage = $this->Storage();
return $Storage->Path().'/'.$this->Relative_Path();
}
public function Relative_Path() {
$event_path = "";
if ( ZM_USE_DEEP_STORAGE )
{
$event_path =
$this->{'MonitorId'}
.'/'.strftime( "%y/%m/%d/%H/%M/%S",
$this->Time()
)
;
}
else
{
$event_path =
$this->{'MonitorId'}
.'/'.$this->{'Id'}
;
}
return( $event_path );
}
public function getImageSrc( ) {
return ZM_BASE_URL.'/index.php?view=image&fid='.$this->{'Id'};
} // end function getImageSrc
} # end class
?>

View File

@ -527,6 +527,7 @@ if ( !empty($action) )
'DoNativeMotDet' => 'toggle', 'DoNativeMotDet' => 'toggle',
'Exif' => 'toggle', 'Exif' => 'toggle',
'RTSPDescribe' => 'toggle', 'RTSPDescribe' => 'toggle',
'RecordAudio' => 'toggle',
); );
$columns = getTableColumns( 'Monitors' ); $columns = getTableColumns( 'Monitors' );

View File

@ -104,6 +104,7 @@ define( "CMD_PREV", 12 );
define( "CMD_NEXT", 13 ); define( "CMD_NEXT", 13 );
define( "CMD_SEEK", 14 ); define( "CMD_SEEK", 14 );
define( "CMD_VARPLAY", 15 ); define( "CMD_VARPLAY", 15 );
define( "CMD_QUIT", 17 );
define( "CMD_QUERY", 99 ); define( "CMD_QUERY", 99 );
// //

View File

@ -217,14 +217,20 @@ function getMimeType( $file )
return( trim( exec( 'file -bi '.escapeshellarg( $file ).' 2>/dev/null' ) ) ); return( trim( exec( 'file -bi '.escapeshellarg( $file ).' 2>/dev/null' ) ) );
} }
function outputVideoStream( $id, $src, $width, $height, $format, $title="" ) function outputVideoStream( $id, $src, $width, $height, $format, $title="" ) {
{ echo getVideoStreamHTML( $id, $src, $width, $height, $format, $title );
if ( file_exists( $src ) ) }
function getVideoStreamHTML( $id, $src, $width, $height, $format, $title="" ) {
$html = '';
$width = validInt($width);
$height = validInt($height);
$title = validHtmlStr($title);
if ( file_exists( $src ) ) {
$mimeType = getMimeType( $src ); $mimeType = getMimeType( $src );
else } else {
{ switch( $format ) {
switch( $format )
{
case 'asf' : case 'asf' :
$mimeType = "video/x-ms-asf"; $mimeType = "video/x-ms-asf";
break; break;
@ -252,118 +258,95 @@ function outputVideoStream( $id, $src, $width, $height, $format, $title="" )
} }
if ( !$mimeType || ($mimeType == 'application/octet-stream') ) if ( !$mimeType || ($mimeType == 'application/octet-stream') )
$mimeType = 'video/'.$format; $mimeType = 'video/'.$format;
$objectTag = false; if ( ZM_WEB_USE_OBJECT_TAGS ) {
if ( ZM_WEB_USE_OBJECT_TAGS ) switch( $mimeType ) {
{
switch( $mimeType )
{
case "video/x-ms-asf" : case "video/x-ms-asf" :
case "video/x-msvideo" : case "video/x-msvideo" :
case "video/mp4" : case "video/mp4" :
{ {
if ( isWindows() ) if ( isWindows() ) {
{ return '<object id="'.$id.'" width="'.$width.'" height="'.$height.'
?>
<object id="<?php echo $id ?>" width="<?php echo validNum($width) ?>" height="<?php echo validNum($height) ?>"
classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95" classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95"
codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,0,02,902" codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,0,02,902"
standby="Loading Microsoft Windows Media Player components..." standby="Loading Microsoft Windows Media Player components..."
type="<?php echo $mimeType ?>"> type="'.$mimeType.'">
<param name="FileName" value="<?php echo $src ?>"/> <param name="FileName" value="'.$src.'"/>
<param name="autoStart" value="1"/> <param name="autoStart" value="1"/>
<param name="showControls" value="0"/> <param name="showControls" value="0"/>
<embed type="<?php echo $mimeType ?>" <embed type="'.$mimeType.'"
pluginspage="http://www.microsoft.com/Windows/MediaPlayer/" pluginspage="http://www.microsoft.com/Windows/MediaPlayer/"
src="<?php echo $src ?>" src="'.$src.'"
name="<?php echo validHtmlStr($title) ?>" name="'.$title.'"
width="<?php echo validNum($width) ?>" width="'.$width.'"
height="<?php echo validInt($height) ?>" height="'.$height.'"
autostart="1" autostart="1"
showcontrols="0"> showcontrols="0">
</embed> </embed>
</object> </object>';
<?php
$objectTag = true;
} }
break;
} }
case "video/quicktime" : case "video/quicktime" :
{ {
?> return '<object id="'.$id.'" width="'.$width.'" height="'.$height.'"
<object id="<?php echo $id ?>" width="<?php echo $width ?>" height="<?php echo $height ?>"
classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
codebase="http://www.apple.com/qtactivex/qtplugin.cab" codebase="http://www.apple.com/qtactivex/qtplugin.cab"
type="<?php echo $mimeType ?>"> type="'.$mimeType.'">
<param name="src" value="<?php echo $src ?>"/> <param name="src" value="'.$src.'"/>
<param name="autoplay" VALUE="true"/> <param name="autoplay" VALUE="true"/>
<param name="controller" VALUE="false"/> <param name="controller" VALUE="false"/>
<embed type="<?php echo $mimeType ?>" <embed type="'.$mimeType.'"
src="<?php echo $src ?>" src="'.$src.'"
pluginspage="http://www.apple.com/quicktime/download/" pluginspage="http://www.apple.com/quicktime/download/"
name="<?php echo validHtmlStr($title) ?>" name="'.$title.'" width="'.$width.'" height="'.$height.'"
width="<?php echo validInt($width) ?>"
height="<?php echo validInt($height) ?>"
autoplay="true" autoplay="true"
controller="true"> controller="true">
</embed> </embed>
</object> </object>';
<?php
$objectTag = true;
break;
} }
case "application/x-shockwave-flash" : case "application/x-shockwave-flash" :
{ {
?> return '<object id="'.$id.'" width="'.$width.'" height="'.$height.'"
<object id="<?php echo $id ?>" width="<?php echo $width ?>" height="<?php echo $height ?>"
classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"
type="<?php echo $mimeType ?>"> type="'.$mimeType.'">
<param name="movie" value="<?php echo $src ?>"/> <param name="movie" value="'.$src.'"/>
<param name="quality" value="high"/> <param name="quality" value="high"/>
<param name="bgcolor" value="#ffffff"/> <param name="bgcolor" value="#ffffff"/>
<embed type="<?php echo $mimeType ?>" <embed type="'.$mimeType.'"
pluginspage="http://www.macromedia.com/go/getflashplayer" pluginspage="http://www.macromedia.com/go/getflashplayer"
src="<?php echo $src ?>" src="'.$src.'"
name="<?php echo validHtmlStr($title) ?>" name="'.$title.'"
width="<?php echo validInt($width) ?>" width="'.$width.'"
height="<?php echo validInt($height) ?>" height="'.$height.'"
quality="high" quality="high"
bgcolor="#ffffff"> bgcolor="#ffffff">
</embed> </embed>
</object> </object>';
<?php
$objectTag = true;
break;
} }
} } # end switch
} } # end if use object tags
if ( !$objectTag ) return '<embed'. ( isset($mimeType)?(' type="'.$mimeType.'"'):'' ). '
{ src="'.$src.'"
?> name="'.$title.'"
<embed<?php echo isset($mimeType)?(' type="'.$mimeType.'"'):"" ?> width="'.$width.'"
src="<?php echo $src ?>" height="'.$height.'"
name="<?php echo validHtmlStr($title) ?>"
width="<?php echo validInt($width) ?>"
height="<?php echo validInt($height) ?>"
autostart="1" autostart="1"
autoplay="1" autoplay="1"
showcontrols="0" showcontrols="0"
controller="0"> controller="0">
</embed> </embed>';
<?php
}
} }
function outputImageStream( $id, $src, $width, $height, $title="" ) function outputImageStream( $id, $src, $width, $height, $title="" ) {
{ echo getImageStream( $id, $src, $width, $height, $title );
}
function getImageStream( $id, $src, $width, $height, $title="" ) {
if ( canStreamIframe() ) { if ( canStreamIframe() ) {
?> return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" width="'. validInt($width)." height=".validInt($height).'"/>';
<iframe id="<?php echo $id ?>" src="<?php echo $src ?>" alt="<?php echo validHtmlStr($title) ?>" width="<?php echo $width ?>" height="<?php echo $height ?>"/>
<?php
} else { } else {
?> return '<img id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" width="'. validInt($width) .'" height="'. validInt( $height ).'"/>';
<img id="<?php echo $id ?>" src="<?php echo $src ?>" alt="<?php echo validHtmlStr($title) ?>" width="<?php echo $width ?>" height="<?php echo $height ?>"/>
<?php
} }
} }
@ -1685,7 +1668,11 @@ function getDiskPercent()
Error("disk_total_space returned false for " . ZM_DIR_EVENTS ); Error("disk_total_space returned false for " . ZM_DIR_EVENTS );
return 0; return 0;
} }
$space = round(($total - disk_free_space(ZM_DIR_EVENTS)) / $total * 100); $free = disk_free_space(ZM_DIR_EVENTS);
if ( ! $free ) {
Error("disk_free_space returned false for " . ZM_DIR_EVENTS );
}
$space = round(($total - $free) / $total * 100);
return( $space ); return( $space );
} }
@ -2507,11 +2494,11 @@ function getStreamHTML( $monitor, $scale=100 ) {
//FIXME, the width and height of the image need to be scaled. //FIXME, the width and height of the image need to be scaled.
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) { if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
$streamSrc = $monitor->getStreamSrc( array( "mode=mpeg", "scale=".$scale, "bitrate=".ZM_WEB_VIDEO_BITRATE, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "format=".ZM_MPEG_LIVE_FORMAT ) ); $streamSrc = $monitor->getStreamSrc( array( "mode=mpeg", "scale=".$scale, "bitrate=".ZM_WEB_VIDEO_BITRATE, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "format=".ZM_MPEG_LIVE_FORMAT ) );
outputVideoStream( "liveStream", $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), ZM_MPEG_LIVE_FORMAT, $monitor->Name() ); return getVideoStream( "liveStream", $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), ZM_MPEG_LIVE_FORMAT, $monitor->Name() );
} else if ( canStream() ) { } else if ( canStream() ) {
$streamSrc = $monitor->getStreamSrc( array( 'mode=jpeg', 'scale='.$scale, 'maxfps='.ZM_WEB_VIDEO_MAXFPS, 'buffer='.$monitor->StreamReplayBuffer() ) ); $streamSrc = $monitor->getStreamSrc( array( 'mode=jpeg', 'scale='.$scale, 'maxfps='.ZM_WEB_VIDEO_MAXFPS, 'buffer='.$monitor->StreamReplayBuffer() ) );
if ( canStreamNative() ) if ( canStreamNative() )
outputImageStream( "liveStream", $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), $monitor->Name() ); return getImageStream( "liveStream", $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), $monitor->Name() );
elseif ( canStreamApplet() ) elseif ( canStreamApplet() )
outputHelperStream( "liveStream", $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), $monitor->Name() ); outputHelperStream( "liveStream", $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), $monitor->Name() );
} else { } else {

View File

@ -230,6 +230,7 @@ $SLANG = array(
'ChooseLogFormat' => 'Choose a log format', 'ChooseLogFormat' => 'Choose a log format',
'ChooseLogSelection' => 'Choose a log selection', 'ChooseLogSelection' => 'Choose a log selection',
'ChoosePreset' => 'Choose Preset', 'ChoosePreset' => 'Choose Preset',
'CloneMonitor' => 'Clone Monitor',
'Close' => 'Close', 'Close' => 'Close',
'Colour' => 'Colour', 'Colour' => 'Colour',
'Command' => 'Command', 'Command' => 'Command',

View File

@ -15,7 +15,6 @@
#menuBar1 { #menuBar1 {
width: 100%; width: 100%;
height: 1.5em;
padding: 3px 0; padding: 3px 0;
text-align: center; text-align: center;
clear: both; clear: both;
@ -41,7 +40,6 @@
#menuBar2 { #menuBar2 {
width: 100%; width: 100%;
height: 1.2em;
padding: 3px 0; padding: 3px 0;
margin-bottom: 4px; margin-bottom: 4px;
} }
@ -57,6 +55,16 @@
text-align: right; text-align: right;
} }
#menuBar1:after,
#menuBar2:after {
content: ".";
display: block;
height: 0;
font-size: 0;
clear: both;
visibility: hidden;
}
#imageFeed { #imageFeed {
text-align: center; text-align: center;
} }

View File

@ -15,12 +15,12 @@
#menuBar1 { #menuBar1 {
width: 100%; width: 100%;
height: 1.5em;
padding: 3px 0; padding: 3px 0;
text-align: center; text-align: center;
clear: both; clear: both;
} }
#menuBar1 #nameControl { #menuBar1 #nameControl {
float: left; float: left;
} }
@ -41,7 +41,6 @@
#menuBar2 { #menuBar2 {
width: 100%; width: 100%;
height: 1.2em;
padding: 3px 0; padding: 3px 0;
margin-bottom: 4px; margin-bottom: 4px;
} }
@ -56,6 +55,15 @@
float: right; float: right;
text-align: right; text-align: right;
} }
#menuBar1:after,
#menuBar2:after {
content: ".";
display: block;
height: 0;
font-size: 0;
clear: both;
visibility: hidden;
}
#imageFeed { #imageFeed {
text-align: center; text-align: center;

View File

@ -30,7 +30,7 @@ function getControlCommands( $monitor )
$cmds['PresetGoto'] = "presetGoto"; $cmds['PresetGoto'] = "presetGoto";
$cmds['PresetHome'] = "presetHome"; $cmds['PresetHome'] = "presetHome";
if ( !empty($monitor->CanZoom) ) if ( !empty($monitor->CanZoom()) )
{ {
if ( $monitor->CanZoomCon() ) if ( $monitor->CanZoomCon() )
$cmds['ZoomRoot'] = "zoomCon"; $cmds['ZoomRoot'] = "zoomCon";
@ -45,7 +45,7 @@ function getControlCommands( $monitor )
$cmds['ZoomMan'] = "zoomMan"; $cmds['ZoomMan'] = "zoomMan";
} }
if ( !empty($monitor->CanFocus) ) if ( !empty($monitor->CanFocus()) )
{ {
if ( $monitor->CanFocusCon() ) if ( $monitor->CanFocusCon() )
$cmds['FocusRoot'] = "focusCon"; $cmds['FocusRoot'] = "focusCon";
@ -60,7 +60,7 @@ function getControlCommands( $monitor )
$cmds['FocusMan'] = "focusMan"; $cmds['FocusMan'] = "focusMan";
} }
if ( !empty($monitor->CanIris) ) if ( !empty($monitor->CanIris()) )
{ {
if ( $monitor->CanIrisCon() ) if ( $monitor->CanIrisCon() )
$cmds['IrisRoot'] = "irisCon"; $cmds['IrisRoot'] = "irisCon";
@ -75,7 +75,7 @@ function getControlCommands( $monitor )
$cmds['IrisMan'] = "irisMan"; $cmds['IrisMan'] = "irisMan";
} }
if ( !empty($monitor->CanWhite) ) if ( !empty($monitor->CanWhite()) )
{ {
if ( $monitor->CanWhiteCon() ) if ( $monitor->CanWhiteCon() )
$cmds['WhiteRoot'] = "whiteCon"; $cmds['WhiteRoot'] = "whiteCon";
@ -89,7 +89,7 @@ function getControlCommands( $monitor )
$cmds['WhiteMan'] = "whiteMan"; $cmds['WhiteMan'] = "whiteMan";
} }
if ( !empty($monitor->CanGain) ) if ( !empty($monitor->CanGain()) )
{ {
if ( $monitor->CanGainCon() ) if ( $monitor->CanGainCon() )
$cmds['GainRoot'] = "gainCon"; $cmds['GainRoot'] = "gainCon";
@ -103,7 +103,7 @@ function getControlCommands( $monitor )
$cmds['GainMan'] = "gainMan"; $cmds['GainMan'] = "gainMan";
} }
if ( !empty($monitor->CanMove) ) if ( !empty($monitor->CanMove()) )
{ {
if ( $monitor->CanMoveCon() ) if ( $monitor->CanMoveCon() )
{ {
@ -246,9 +246,9 @@ function controlPanTilt( $monitor, $cmds )
<div class="pantiltLabel"><?php echo translate('PanTilt') ?></div> <div class="pantiltLabel"><?php echo translate('PanTilt') ?></div>
<div class="pantiltButtons"> <div class="pantiltButtons">
<?php <?php
$hasPan = $monitor->CanPan; $hasPan = $monitor->CanPan();
$hasTilt = $monitor->CanTilt; $hasTilt = $monitor->CanTilt();
$hasDiag = $hasPan && $hasTilt && $monitor->CanMoveDiag; $hasDiag = $hasPan && $hasTilt && $monitor->CanMoveDiag();
?> ?>
<div class="arrowBtn upLeftBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUpLeft'] ?>',event,-1,-1)"></div> <div class="arrowBtn upLeftBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUpLeft'] ?>',event,-1,-1)"></div>
<div class="arrowBtn upBtn<?php echo $hasTilt?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUp'] ?>',event,0,-1)"></div> <div class="arrowBtn upBtn<?php echo $hasTilt?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUp'] ?>',event,0,-1)"></div>
@ -278,7 +278,7 @@ function controlPresets( $monitor, $cmds )
$labels[$row['Preset']] = $row['Label']; $labels[$row['Preset']] = $row['Label'];
} }
$presetBreak = (int)(($monitor->NumPresets+1)/((int)(($monitor->NumPresets-1)/MAX_PRESETS)+1)); $presetBreak = (int)(($monitor->NumPresets()+1)/((int)(($monitor->NumPresets()-1)/MAX_PRESETS)+1));
ob_start(); ob_start();
?> ?>
@ -286,7 +286,7 @@ function controlPresets( $monitor, $cmds )
<!--<div><?php echo translate('Presets') ?></div>--> <!--<div><?php echo translate('Presets') ?></div>-->
<div> <div>
<?php <?php
for ( $i = 1; $i <= $monitor->NumPresets; $i++ ) for ( $i = 1; $i <= $monitor->NumPresets(); $i++ )
{ {
?><input type="button" class="ptzNumBtn" title="<?php echo isset($labels[$i])?$labels[$i]:"" ?>" value="<?php echo $i ?>" onclick="controlCmd('<?php echo $cmds['PresetGoto'] ?><?php echo $i ?>');"/><?php ?><input type="button" class="ptzNumBtn" title="<?php echo isset($labels[$i])?$labels[$i]:"" ?>" value="<?php echo $i ?>" onclick="controlCmd('<?php echo $cmds['PresetGoto'] ?><?php echo $i ?>');"/><?php
if ( $i && (($i%$presetBreak) == 0) ) if ( $i && (($i%$presetBreak) == 0) )

View File

@ -589,7 +589,6 @@ else if (document.layers) window.onload=start_slider;
function exportEventImagesMaster( $eids ) function exportEventImagesMaster( $eids )
{ {
global $SLANG;
ob_start(); ob_start();
exportHeader( translate('Images').' Master' ); exportHeader( translate('Images').' Master' );
?> ?>

View File

@ -48,7 +48,7 @@ var popupSizes = {
'log': { 'width': 1080, 'height': 720 }, 'log': { 'width': 1080, 'height': 720 },
'login': { 'width': 720, 'height': 480 }, 'login': { 'width': 720, 'height': 480 },
'logout': { 'width': 260, 'height': 100 }, 'logout': { 'width': 260, 'height': 100 },
'monitor': { 'width': 450, 'height': 440 }, 'monitor': { 'width': 700, 'height': 640 },
'monitorpreset':{ 'width': 440, 'height': 200 }, 'monitorpreset':{ 'width': 440, 'height': 200 },
'monitorprobe': { 'width': 500, 'height': 240 }, 'monitorprobe': { 'width': 500, 'height': 240 },
'monitorselect':{ 'width': 160, 'height': 200 }, 'monitorselect':{ 'width': 160, 'height': 200 },

View File

@ -48,7 +48,7 @@ var popupSizes = {
'log': { 'width': 1080, 'height': 720 }, 'log': { 'width': 1080, 'height': 720 },
'login': { 'width': 720, 'height': 480 }, 'login': { 'width': 720, 'height': 480 },
'logout': { 'width': 260, 'height': 150 }, 'logout': { 'width': 260, 'height': 150 },
'monitor': { 'width': 600, 'height': 780 }, 'monitor': { 'width': 800, 'height': 780 },
'monitorpreset':{ 'width': 440, 'height': 200 }, 'monitorpreset':{ 'width': 440, 'height': 200 },
'monitorprobe': { 'width': 500, 'height': 240 }, 'monitorprobe': { 'width': 500, 'height': 240 },
'monitorselect':{ 'width': 160, 'height': 200 }, 'monitorselect':{ 'width': 160, 'height': 200 },

View File

@ -54,7 +54,9 @@ if ( canEdit('Monitors') )
if ( $show_storage_areas ) { $columns += 1; } if ( $show_storage_areas ) { $columns += 1; }
echo $columns; echo $columns;
?>"> ?>">
<input type="button" class="btn btn-default" value="<?php echo translate('AddNewMonitor'); ?>" onclick="createPopup( '?view=monitor', 'zmMonitor0', 'monitor' ); return( false );"></input> <input type="button" name="addBtn" value="<?php echo translate('AddNewMonitor') ?>" onclick="addMonitor( this )"/>
<!-- <?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> -->
</td> </td>
<?php <?php
for ( $i = 0; $i < count($eventCounts); $i++ ) for ( $i = 0; $i < count($eventCounts); $i++ )

View File

@ -27,7 +27,7 @@ if ( !canView( 'Events' ) )
$eid = validInt( $_REQUEST['eid'] ); $eid = validInt( $_REQUEST['eid'] );
$fid = !empty($_REQUEST['fid'])?validInt($_REQUEST['fid']):1; $fid = !empty($_REQUEST['fid'])?validInt($_REQUEST['fid']):1;
$sql = 'SELECT E.*,M.Name AS MonitorName,M.Width,M.Height,M.DefaultRate,M.DefaultScale,M.VideoWriter,M.SaveJPEGs,M.Orientation,M.LabelFormat FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE E.Id = ?'; $sql = 'SELECT E.*,M.Name AS MonitorName,E.Width,E.Height,M.DefaultRate,M.DefaultScale,M.VideoWriter,M.SaveJPEGs,M.Orientation,M.LabelFormat FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE E.Id = ?';
$sql_values = array( $eid ); $sql_values = array( $eid );
if ( $user['MonitorIds'] ) { if ( $user['MonitorIds'] ) {

View File

@ -66,13 +66,11 @@ if ( !empty($limit) && $nEvents > $limit )
$nEvents = $limit; $nEvents = $limit;
} }
$pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE); $pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE);
if ( $pages > 1 ) { if ( !empty($page) ) {
if ( !empty($page) ) {
if ( $page < 0 ) if ( $page < 0 )
$page = 1; $page = 1;
if ( $page > $pages ) if ( $page > $pages )
$page = $pages; $page = $pages;
}
} }
if ( !empty($page) ) { if ( !empty($page) ) {
$limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE); $limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE);

View File

@ -23,6 +23,7 @@ if ( !canView( 'Events' ) )
$view = "error"; $view = "error";
return; return;
} }
require_once('includes/Frame.php');
$eid = validInt($_REQUEST['eid']); $eid = validInt($_REQUEST['eid']);
if ( !empty($_REQUEST['fid']) ) if ( !empty($_REQUEST['fid']) )
@ -38,58 +39,60 @@ if ( !empty($fid) ) {
} else { } else {
$frame = dbFetchOne( 'SELECT * FROM Frames WHERE EventId = ? AND Score = ?', NULL, array( $eid, $event['MaxScore'] ) ); $frame = dbFetchOne( 'SELECT * FROM Frames WHERE EventId = ? AND Score = ?', NULL, array( $eid, $event['MaxScore'] ) );
} }
$frame = new Frame( $frame );
$maxFid = $event['Frames']; $maxFid = $event['Frames'];
$firstFid = 1; $firstFid = 1;
$prevFid = $frame['FrameId']-1; $prevFid = $frame->FrameId()-1;
$nextFid = $frame['FrameId']+1; $nextFid = $frame->FrameId()+1;
$lastFid = $maxFid; $lastFid = $maxFid;
$alarmFrame = $frame['Type']=='Alarm'; $alarmFrame = $frame->Type()=='Alarm';
if ( isset( $_REQUEST['scale'] ) ) if ( isset( $_REQUEST['scale'] ) )
$scale = validInt($_REQUEST['scale']); $scale = validInt($_REQUEST['scale']);
else else
$scale = max( reScale( SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE ); $scale = max( reScale( SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
$imageData = getImageSrc( $event, $frame, $scale, (isset($_REQUEST['show']) && $_REQUEST['show']=="capt") ); $imageData = getImageSrc( $event, $frame->FrameId(), $scale, (isset($_REQUEST['show']) && $_REQUEST['show']=="capt") );
$imagePath = $imageData['thumbPath']; $imagePath = $imageData['thumbPath'];
$eventPath = $imageData['eventPath']; $eventPath = $imageData['eventPath'];
$dImagePath = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-diag-d.jpg", $eventPath, $frame['FrameId'] ); $dImagePath = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-diag-d.jpg", $eventPath, $frame->FrameId() );
$rImagePath = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-diag-r.jpg", $eventPath, $frame['FrameId'] ); $rImagePath = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-diag-r.jpg", $eventPath, $frame->FrameId() );
$focusWindow = true; $focusWindow = true;
xhtmlHeaders(__FILE__, translate('Frame')." - ".$event['Id']." - ".$frame['FrameId'] ); xhtmlHeaders(__FILE__, translate('Frame')." - ".$event['Id']." - ".$frame->FrameId() );
?> ?>
<body> <body>
<div id="page"> <div id="page">
<div id="header"> <div id="header">
<div id="headerButtons"> <div id="headerButtons">
<?php if ( ZM_RECORD_EVENT_STATS && $alarmFrame ) { echo makePopupLink( '?view=stats&amp;eid='.$event['Id'].'&amp;fid='.$frame['FrameId'], 'zmStats', 'stats', translate('Stats') ); } ?> <?php if ( ZM_RECORD_EVENT_STATS && $alarmFrame ) { echo makePopupLink( '?view=stats&amp;eid='.$event['Id'].'&amp;fid='.$frame->FrameId(), 'zmStats', 'stats', translate('Stats') ); } ?>
<?php if ( canEdit( 'Events' ) ) { ?><a href="?view=none&amp;action=delete&amp;markEid=<?php echo $event['Id'] ?>"><?php echo translate('Delete') ?></a><?php } ?> <?php if ( canEdit( 'Events' ) ) { ?><a href="?view=none&amp;action=delete&amp;markEid=<?php echo $event['Id'] ?>"><?php echo translate('Delete') ?></a><?php } ?>
<a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a> <a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a>
</div> </div>
<h2><?php echo translate('Frame') ?> <?php echo $event['Id']."-".$frame['FrameId']." (".$frame['Score'].")" ?></h2> <h2><?php echo translate('Frame') ?> <?php echo $event['Id']."-".$frame->FrameId()." (".$frame->Score().")" ?></h2>
</div> </div>
<div id="content"> <div id="content">
<p id="image"> <p id="image">
<?php if ( in_array($event['VideoWriter'],array("1","2")) ) { ?> <?php if ( in_array($event['VideoWriter'],array("1","2")) ) { ?>
<img src="?view=image-ffmpeg&eid=<?php echo $event['Id'] ?>&fid=<?php echo $frame['FrameId'] ?>&scale=<?php echo $event['DefaultScale'] ?>" class="<?php echo $imageData['imageClass'] ?>"> <img src="?view=image-ffmpeg&eid=<?php echo $event['Id'] ?>&fid=<?php echo $frame->FrameId() ?>&scale=<?php echo $event['DefaultScale'] ?>" class="<?php echo $imageData['imageClass'] ?>">
<?php } else { <?php } else {
if ( $imageData['hasAnalImage'] ) { ?><a href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $frame['FrameId'] ?>&amp;scale=<?php echo $scale ?>&amp;show=<?php echo $imageData['isAnalImage']?"capt":"anal" ?>"><?php } ?><img src="<?php echo viewImagePath( $imagePath ) ?>" width="<?php echo reScale( $event['Width'], $event['DefaultScale'], $scale ) ?>" height="<?php echo reScale( $event['Height'], $event['DefaultScale'], $scale ) ?>" alt="<?php echo $frame['EventId']."-".$frame['FrameId'] ?>" class="<?php echo $imageData['imageClass'] ?>"/><?php if ( $imageData['hasAnalImage'] ) { ?></a><?php } ?> if ( $imageData['hasAnalImage'] ) { ?><a href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $frame->FrameId() ?>&amp;scale=<?php echo $scale ?>&amp;show=<?php echo $imageData['isAnalImage']?"capt":"anal" ?>"><?php } ?>
<img src="<?php echo $frame->getImageSrc() ?>" width="<?php echo reScale( $event['Width'], $event['DefaultScale'], $scale ) ?>" height="<?php echo reScale( $event['Height'], $event['DefaultScale'], $scale ) ?>" alt="<?php echo $frame->EventId()."-".$frame->FrameId() ?>" class="<?php echo $imageData['imageClass'] ?>"/><?php if ( $imageData['hasAnalImage'] ) { ?></a><?php } ?>
<?php } ?> <?php } ?>
</p> </p>
<p id="controls"> <p id="controls">
<?php if ( $frame['FrameId'] > 1 ) { ?> <?php if ( $frame->FrameId() > 1 ) { ?>
<a id="firstLink" href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $firstFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('First') ?></a> <a id="firstLink" href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $firstFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('First') ?></a>
<?php } if ( $frame['FrameId'] > 1 ) { ?> <?php } if ( $frame->FrameId() > 1 ) { ?>
<a id="prevLink" href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $prevFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('Prev') ?></a> <a id="prevLink" href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $prevFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('Prev') ?></a>
<?php } if ( $frame['FrameId'] < $maxFid ) { ?> <?php } if ( $frame->FrameId() < $maxFid ) { ?>
<a id="nextLink" href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $nextFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('Next') ?></a> <a id="nextLink" href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $nextFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('Next') ?></a>
<?php } if ( $frame['FrameId'] < $maxFid ) { ?> <?php } if ( $frame->FrameId() < $maxFid ) { ?>
<a id="lastLink" href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $lastFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('Last') ?></a> <a id="lastLink" href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $lastFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('Last') ?></a>
<?php } ?> <?php } ?>
</p> </p>

View File

@ -205,14 +205,9 @@ $versionClass = (ZM_DYN_DB_VERSION&&(ZM_DYN_DB_VERSION!=ZM_VERSION))?'errorText'
<?php if ( canView( 'Stream' ) && $cycleCount > 1 ) { <?php if ( canView( 'Stream' ) && $cycleCount > 1 ) {
$cycleGroup = isset($_COOKIE['zmGroup'])?$_COOKIE['zmGroup']:0; $cycleGroup = isset($_COOKIE['zmGroup'])?$_COOKIE['zmGroup']:0;
?> ?>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Montage <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><?php echo makePopupLink( '?view=cycle&amp;group='.$cycleGroup, 'zmCycle'.$cycleGroup, array( 'cycle', $cycleWidth, $cycleHeight ), translate('Cycle'), $running ) ?></li> <li><?php echo makePopupLink( '?view=cycle&amp;group='.$cycleGroup, 'zmCycle'.$cycleGroup, array( 'cycle', $cycleWidth, $cycleHeight ), translate('Cycle'), $running ) ?></li>
<li><?php echo makePopupLink( '?view=montage&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montage', translate('Montage'), $running ) ?></li> <li><?php echo makePopupLink( '?view=montage&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montage', translate('Montage'), $running ) ?></li>
<li><?php echo makePopupLink( '?view=montagereview&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montagereview', translate('Montage Review'), $running ) ?></li> <li><?php echo makePopupLink( '?view=montagereview&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montagereview', translate('Montage Review'), $running ) ?></li>
</ul>
</li>
<?php } ?> <?php } ?>
</ul> </ul>

View File

@ -1,3 +1,6 @@
var jsTranslatedAddText;
var jsTranslatedCloneText;
function setButtonStates( element ) function setButtonStates( element )
{ {
var form = element.form; var form = element.form;
@ -12,21 +15,37 @@ function setButtonStates( element )
break; break;
} }
} }
else if ( form.elements[i].length ) }
$(element).getParent( 'tr' ).toggleClass( 'highlight' );
form.editBtn.disabled = (checked!=1);
form.addBtn.value = (checked==1) ? jsTranslatedCloneText:jsTranslatedAddText;
form.deleteBtn.disabled = (checked==0);
}
function addMonitor( element)
{
var form = element.form;
var dupParam;
var monitorId=-1;
if (form.addBtn.value == jsTranslatedCloneText)
{ {
for( var j = 0, j_length = form.elements[i].length; j < j_length; j += 1 ) { // get the value of the first checkbox
if ( form.elements[j].type == "checkbox" ) { for ( var i = 0; i < form.elements.length; i++ )
if ( form.elements[j].checked ) { {
if ( checked++ > 1 ) if ( form.elements[i].type == "checkbox" )
{
if ( form.elements[i].checked )
{
monitorId = form.elements[i].value;
break; break;
} }
} }
} // end foreach element in array
} }
} // end foreach element in array }
$(element).getParent( 'tr' ).toggleClass( 'highlight' ); dupParam = (monitorId == -1 ) ? '': '&dupId='+monitorId;
form.editBtn.disabled = (checked!=1); createPopup( '?view=monitor'+dupParam, 'zmMonitor0','monitor' );
form.deleteBtn.disabled = (checked==0);
} }
function editMonitor( element ) function editMonitor( element )
@ -66,6 +85,8 @@ function reloadWindow()
function initPage() function initPage()
{ {
jsTranslatedAddText = translatedAddText;
jsTranslatedCloneText = translatedCloneText;
reloadWindow.periodical( consoleRefreshTimeout ); reloadWindow.periodical( consoleRefreshTimeout );
if ( showVersionPopup ) if ( showVersionPopup )
createPopup( '?view=version', 'zmVersion', 'version' ); createPopup( '?view=version', 'zmVersion', 'version' );

View File

@ -26,7 +26,7 @@ elseif ( ZM_DYN_SHOW_DONATE_REMINDER )
?> ?>
var showVersionPopup = <?php echo isset($showVersionPopup )?'true':'false' ?>; var showVersionPopup = <?php echo isset($showVersionPopup )?'true':'false' ?>;
var showDonatePopup = <?php echo isset($showDonatePopup )?'true':'false' ?>; var showDonatePopup = <?php echo isset($showDonatePopup )?'true':'false' ?>;
var translatedAddText = "<?php echo translate('AddNewMonitor') ?>";
var translatedCloneText = "<?php echo translate('CloneMonitor') ?>";

View File

@ -35,6 +35,7 @@ function Monitor( index, id, connKey )
if ( this.streamCmdTimer ) if ( this.streamCmdTimer )
this.streamCmdTimer = clearTimeout( this.streamCmdTimer ); this.streamCmdTimer = clearTimeout( this.streamCmdTimer );
var stream = document.getElementById( "liveStream"+this.id );
if ( respObj.result == 'Ok' ) if ( respObj.result == 'Ok' )
{ {
this.status = respObj.status; this.status = respObj.status;
@ -57,7 +58,6 @@ function Monitor( index, id, connKey )
this.setStateClass( $('monitor'+this.index), stateClass ); this.setStateClass( $('monitor'+this.index), stateClass );
/*Stream could be an applet so can't use moo tools*/ /*Stream could be an applet so can't use moo tools*/
var stream = document.getElementById( "liveStream"+this.id );
stream.className = stateClass; stream.className = stateClass;
var isAlarmed = ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT ); var isAlarmed = ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT );
@ -90,6 +90,10 @@ function Monitor( index, id, connKey )
else else
{ {
console.error( respObj.message ); console.error( respObj.message );
// Try to reload the image stream.
if ( stream )
stream.src = stream.src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
} }
var streamCmdTimeout = statusRefreshTimeout; var streamCmdTimeout = statusRefreshTimeout;
if ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT ) if ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT )

View File

@ -475,8 +475,211 @@ function drawZonePoints()
updateZoneImage(); updateZoneImage();
} }
function initPage() //
// Imported from watch.js and modified for new zone edit view
//
var alarmState = STATE_IDLE;
var lastAlarmState = STATE_IDLE;
function setAlarmState( currentAlarmState ) {
alarmState = currentAlarmState;
var stateString = "Unknown";
var stateClass = "";
if ( alarmState == STATE_ALARM )
stateClass = "alarm";
else if ( alarmState == STATE_ALERT )
stateClass = "alert";
$('stateValue').set( 'text', stateStrings[alarmState] );
if ( stateClass )
$('stateValue').setProperty( 'class', stateClass );
else
$('stateValue').removeProperty( 'class' );
var isAlarmed = ( alarmState == STATE_ALARM || alarmState == STATE_ALERT );
var wasAlarmed = ( lastAlarmState == STATE_ALARM || lastAlarmState == STATE_ALERT );
var newAlarm = ( isAlarmed && !wasAlarmed );
var oldAlarm = ( !isAlarmed && wasAlarmed );
if ( newAlarm )
{
if ( SOUND_ON_ALARM )
{
// Enable the alarm sound
if ( !canPlayPauseAudio )
$('alarmSound').removeClass( 'hidden' );
else
$('MediaPlayer').Play();
}
}
if ( SOUND_ON_ALARM )
{
if ( oldAlarm )
{
// Disable alarm sound
if ( !canPlayPauseAudio )
$('alarmSound').addClass( 'hidden' );
else
$('MediaPlayer').Stop();
}
}
lastAlarmState = alarmState;
}
var streamCmdParms = "view=request&request=stream&connkey="+connKey;
var streamCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStreamCmdResponse } );
var streamCmdTimer = null;
var streamStatus;
function getStreamCmdResponse( respObj, respText ) {
watchdogOk("stream");
if ( streamCmdTimer )
streamCmdTimer = clearTimeout( streamCmdTimer );
if ( respObj.result == 'Ok' ) {
streamStatus = respObj.status;
$('fpsValue').set( 'text', streamStatus.fps );
setAlarmState( streamStatus.state );
var delayString = secsToTime( streamStatus.delay );
if ( streamStatus.paused == true )
{
streamCmdPause( false );
} else if ( streamStatus.delayed == true && streamStatus.rate == 1 ) {
streamCmdPlay( false );
}
} else {
checkStreamForErrors("getStreamCmdResponse",respObj);//log them
// Try to reload the image stream.
var streamImg = document.getElementById('liveStream');
if ( streamImg )
streamImg.src = streamImg.src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
}
var streamCmdTimeout = statusRefreshTimeout;
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT )
streamCmdTimeout = streamCmdTimeout/5;
streamCmdTimer = streamCmdQuery.delay( streamCmdTimeout );
}
var streamPause = false;
function streamCmdPauseToggle() {
if ( streamPause == true ) {
streamCmdPlay( true );
streamPause = false;
document.getElementById("pauseBtn").value = pauseString;
} else {
streamCmdPause( true );
streamPause = true;
document.getElementById("pauseBtn").value = playString;
}
}
function streamCmdPause( action ) {
if ( action )
streamCmdReq.send( streamCmdParms+"&command="+CMD_PAUSE );
}
function streamCmdPlay( action )
{ {
if ( action )
streamCmdReq.send( streamCmdParms+"&command="+CMD_PLAY );
}
function streamCmdStop( action ) {
if ( action )
streamCmdReq.send( streamCmdParms+"&command="+CMD_STOP );
}
function streamCmdQuery() {
streamCmdReq.send( streamCmdParms+"&command="+CMD_QUERY );
}
var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate";
var statusCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', data: statusCmdParms, timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStatusCmdResponse } );
var statusCmdTimer = null;
function getStatusCmdResponse( respObj, respText ) {
watchdogOk("status");
if ( statusCmdTimer )
statusCmdTimer = clearTimeout( statusCmdTimer );
if ( respObj.result == 'Ok' )
{
$('fpsValue').set( 'text', respObj.monitor.FrameRate );
setAlarmState( respObj.monitor.Status );
}
else
checkStreamForErrors("getStatusCmdResponse",respObj);
var statusCmdTimeout = statusRefreshTimeout;
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT )
statusCmdTimeout = statusCmdTimeout/5;
statusCmdTimer = statusCmdQuery.delay( statusCmdTimeout );
}
function statusCmdQuery() {
statusCmdReq.send();
}
var tempImage = null;
function fetchImage( streamImage ) {
var now = new Date();
if ( !tempImage )
tempImage = new Element( 'img' );
tempImage.setProperty( 'src', streamSrc+'&'+now.getTime() );
$(streamImage).setProperty( 'src', tempImage.getProperty( 'src' ) );
}
function appletRefresh() {
if ( streamStatus && (!streamStatus.paused && !streamStatus.delayed) )
{
var streamImg = $('liveStream');
var parent = streamImg.getParent();
streamImg.dispose();
streamImg.inject( parent );
if ( appletRefreshTime )
appletRefresh.delay( appletRefreshTime*1000 );
}
else
{
appletRefresh.delay( 15*1000 ); //if we are paused or delayed check every 15 seconds if we are live yet...
}
}
var watchdogInactive = {
'stream': false,
'status': false
};
var watchdogFunctions = {
'stream': streamCmdQuery,
'status': statusCmdQuery
};
//Make sure the various refreshes are still taking effect
function watchdogCheck( type ) {
if ( watchdogInactive[type] ) {
console.log( "Detected streamWatch of type: " + type + " stopped, restarting" );
watchdogFunctions[type]();
watchdogInactive[type] = false;
} else {
watchdogInactive[type] = true;
}
}
function watchdogOk( type ) {
watchdogInactive[type] = false;
}
function initPage() {
var form = document.zoneForm; var form = document.zoneForm;
//form.elements['newZone[Name]'].disabled = true; //form.elements['newZone[Name]'].disabled = true;
@ -503,13 +706,37 @@ function initPage()
applyZoneType(); applyZoneType();
if ( form.elements['newZone[Units]'].value == 'Percent' ) if ( form.elements['newZone[Units]'].value == 'Percent' ) {
{
applyZoneUnits(); applyZoneUnits();
} }
applyCheckMethod(); applyCheckMethod();
drawZonePoints(); drawZonePoints();
//
// Imported from watch.js and modified for new zone edit view
//
if ( streamMode == "single" ) {
statusCmdTimer = statusCmdQuery.delay( (Math.random()+0.1)*statusRefreshTimeout );
watchdogCheck.pass('status').periodical(statusRefreshTimeout*2);
} else {
streamCmdTimer = streamCmdQuery.delay( (Math.random()+0.1)*statusRefreshTimeout );
watchdogCheck.pass('stream').periodical(statusRefreshTimeout*2);
}
if ( canStreamNative || streamMode == "single" ) {
var streamImg = $('imageFrame').getElement('img');
if ( !streamImg )
streamImg = $('imageFrame').getElement('object');
if ( streamMode == "single" ) {
streamImg.addEvent( 'click', fetchImage.pass( streamImg ) );
fetchImage.pass( streamImg ).periodical( imageRefreshTimeout );
}
}
if ( refreshApplet && appletRefreshTime )
appletRefresh.delay( appletRefreshTime*1000 );
} }
window.addEvent( 'domready', initPage ); window.addEvent( 'domready', initPage );

View File

@ -65,3 +65,55 @@ var minBlobAreaLtMaxString = '<?php echo addslashes(translate('MinBlobAreaLtMax'
var minBlobLtMinFilterString = '<?php echo addslashes(translate('MinBlobLtMinFilter')) ?>'; var minBlobLtMinFilterString = '<?php echo addslashes(translate('MinBlobLtMinFilter')) ?>';
var minBlobsUnsetString = '<?php echo addslashes(translate('MinBlobsUnset')) ?>'; var minBlobsUnsetString = '<?php echo addslashes(translate('MinBlobsUnset')) ?>';
var minBlobsLtMaxString = '<?php echo addslashes(translate('MinBlobsLtMax')) ?>'; var minBlobsLtMaxString = '<?php echo addslashes(translate('MinBlobsLtMax')) ?>';
//
// Imported from watch.js.php and modified for new zone edit view
//
var STATE_IDLE = <?php echo STATE_IDLE ?>;
var STATE_PREALARM = <?php echo STATE_PREALARM ?>;
var STATE_ALARM = <?php echo STATE_ALARM ?>;
var STATE_ALERT = <?php echo STATE_ALERT ?>;
var STATE_TAPE = <?php echo STATE_TAPE ?>;
var stateStrings = new Array();
stateStrings[STATE_IDLE] = "<?php echo translate('Idle') ?>";
stateStrings[STATE_PREALARM] = "<?php echo translate('Idle') ?>";
stateStrings[STATE_ALARM] = "<?php echo translate('Alarm') ?>";
stateStrings[STATE_ALERT] = "<?php echo translate('Alert') ?>";
stateStrings[STATE_TAPE] = "<?php echo translate('Record') ?>";
var pauseString = "<?php echo translate('Pause') ?>";
var playString = "<?php echo translate('Play') ?>";
var deleteString = "<?php echo translate('Delete') ?>";
var CMD_PAUSE = <?php echo CMD_PAUSE ?>;
var CMD_PLAY = <?php echo CMD_PLAY ?>;
var CMD_STOP = <?php echo CMD_STOP ?>;
var CMD_QUERY = <?php echo CMD_QUERY ?>;
var SCALE_BASE = <?php echo SCALE_BASE ?>;
var SOUND_ON_ALARM = <?php echo ZM_WEB_SOUND_ON_ALARM ?>;
var streamMode = "<?php echo $streamMode ?>";
var connKey = '<?php echo $connkey ?>';
var monitorId = <?php echo $monitor->Id() ?>;
var monitorUrl = '<?php echo ( $monitor->Server()->Url() ) ?>';
var streamSrc = "<?php echo preg_replace( '/&amp;/', '&', $streamSrc ) ?>";
var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
var imageRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_IMAGE ?>;
var canEditMonitors = <?php echo canEdit( 'Monitors' )?'true':'false' ?>;
var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
var canPlayPauseAudio = Browser.ie;
var refreshApplet = <?php echo (canStreamApplet() && $streamMode == "jpeg")?'true':'false' ?>;
var appletRefreshTime = <?php echo ZM_RELOAD_CAMBOZOLA ?>;

View File

@ -0,0 +1,8 @@
var streamCmdParms = "view=request&request=stream&connkey="+connKey;
var streamCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel' } );
function streamCmdQuit( action ) {
if ( action )
streamCmdReq.send( streamCmdParms+"&command="+CMD_QUIT );
}

View File

@ -0,0 +1,4 @@
var connKey = '<?php echo $connkey ?>';
var monitorUrl = '<?php echo ( $monitor->Server()->Url() ) ?>';
var CMD_QUIT = <?php echo CMD_QUIT ?>;

View File

@ -58,6 +58,13 @@ if ( ! empty($_REQUEST['mid']) ) {
} else { } else {
$nextId = getTableAutoInc( 'Monitors' ); $nextId = getTableAutoInc( 'Monitors' );
if ( ! empty( $_REQUEST['dupId'] ) ) {
$monitor = new Monitor( $_REQUEST['dupId'] );
if ( ZM_OPT_X10 )
$x10Monitor = dbFetchOne( 'SELECT * FROM TriggersX10 WHERE MonitorId = ?', NULL, array($_REQUEST['dupId']) );
$clonedName = $monitor->Name();
$monitor->Name( translate('Monitor').'-'.$nextId );
} else {
$monitor = new Monitor(); $monitor = new Monitor();
$monitor->set( array( $monitor->set( array(
'Id' => 0, 'Id' => 0,
@ -131,7 +138,8 @@ if ( ! empty($_REQUEST['mid']) ) {
'ServerId' => $Server['Id'], 'ServerId' => $Server['Id'],
'StorageId' => '', 'StorageId' => '',
) ); ) );
} } # end if $_REQUEST['dupID']
} # end if $_REQUEST['mid']
if ( ZM_OPT_X10 && empty($x10Monitor) ) { if ( ZM_OPT_X10 && empty($x10Monitor) ) {
$x10Monitor = array( $x10Monitor = array(
@ -143,6 +151,7 @@ if ( ZM_OPT_X10 && empty($x10Monitor) ) {
function fourcc( $a, $b, $c, $d ) { function fourcc( $a, $b, $c, $d ) {
return( ord($a) | (ord($b) << 8) | (ord($c) << 16) | (ord($d) << 24) ); return( ord($a) | (ord($b) << 8) | (ord($c) << 16) | (ord($d) << 24) );
} }
if ( isset( $_REQUEST['newMonitor'] ) ) { if ( isset( $_REQUEST['newMonitor'] ) ) {
@ -455,23 +464,22 @@ $videowriteropts = array(
xhtmlHeaders(__FILE__, translate('Monitor')." - ".validHtmlStr($monitor->Name) ); xhtmlHeaders(__FILE__, translate('Monitor')." - ".validHtmlStr($monitor->Name) );
?> ?>
<body> <body>
<div id="page"> <div id="page">
<div id="header"> <div id="header">
<?php if ( canEdit( 'Monitors' ) ) { ?> <?php if ( canEdit( 'Monitors' ) ) { ?>
<?php if ( isset ($_REQUEST['dupId'])) { ?>
<div class="alert alert-info">
Configuration cloned from Monitor: <?php echo $clonedName ?>
</div>
<?php } ?>
<div id="headerButtons"> <div id="headerButtons">
<a href="#" onclick="createPopup( '?view=monitorprobe&amp;mid=<?php echo $monitor->Id ?>', 'zmMonitorProbe<?php echo $monitor->Id ?>', 'monitorprobe' ); return( false );"><?php echo translate('Probe') ?></a> <a href="#" onclick="createPopup( '?view=monitorprobe&amp;mid=<?php echo $monitor->Id ?>', 'zmMonitorProbe<?php echo $monitor->Id ?>', 'monitorprobe' ); return( false );"><?php echo translate('Probe') ?></a>
<?php <?php if ( ZM_HAS_ONVIF ) { ?>
if ( ZM_HAS_ONVIF ) {
?>
<a href="#" onclick="createPopup( '?view=onvifprobe&amp;mid=<?php echo $monitor->Id ?>', 'zmOnvifProbe<?php echo $monitor->Id ?>', 'onvifprobe' ); return( false );"><?php echo translate('OnvifProbe') ?></a> <a href="#" onclick="createPopup( '?view=onvifprobe&amp;mid=<?php echo $monitor->Id ?>', 'zmOnvifProbe<?php echo $monitor->Id ?>', 'onvifprobe' ); return( false );"><?php echo translate('OnvifProbe') ?></a>
<?php <?php } ?>
}
?>
<a href="#" onclick="createPopup( '?view=monitorpreset&amp;mid=<?php echo $monitor->Id ?>', 'zmMonitorPreset<?php echo $monitor->Id ?>', 'monitorpreset' ); return( false );"><?php echo translate('Presets') ?></a> <a href="#" onclick="createPopup( '?view=monitorpreset&amp;mid=<?php echo $monitor->Id ?>', 'zmMonitorPreset<?php echo $monitor->Id ?>', 'monitorpreset' ); return( false );"><?php echo translate('Presets') ?></a>
</div> </div>
<?php <?php } ?>
}
?>
<h2><?php echo translate('Monitor') ?> - <?php echo validHtmlStr($monitor->Name) ?><?php if ( !empty($monitor->Id) ) { ?> (<?php echo $monitor->Id ?>)<?php } ?></h2> <h2><?php echo translate('Monitor') ?> - <?php echo validHtmlStr($monitor->Name) ?><?php if ( !empty($monitor->Id) ) { ?> (<?php echo $monitor->Id ?>)<?php } ?></h2>
</div> </div>
<div id="content"> <div id="content">
@ -717,21 +725,21 @@ switch ( $tab )
</td> </td>
</tr> </tr>
<tr><td><?php echo translate('AnalysisFPS') ?></td><td><input type="text" name="newMonitor[AnalysisFPS]" value="<?php echo validHtmlStr($monitor->AnalysisFPS) ?>" size="6"/></td></tr> <tr><td><?php echo translate('AnalysisFPS') ?></td><td><input type="text" name="newMonitor[AnalysisFPS]" value="<?php echo validHtmlStr($monitor->AnalysisFPS) ?>" size="6"/></td></tr>
<?php <?php if ( $monitor->Type != "Local" && $monitor->Type != "File" ) { ?>
if ( $monitor->Type != "Local" && $monitor->Type != "File" ) <tr>
{ <td><?php echo translate('MaximumFPS') ?>&nbsp;(<?php echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_MAXFPS', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td>
?> <td><input type="text" onclick="document.getElementById('newMonitor[MaxFPS]').innerHTML= ' CAUTION: See the help text'" name="newMonitor[MaxFPS]" value="<?php echo validHtmlStr($monitor->MaxFPS) ?>" size="5"/><span id="newMonitor[MaxFPS]" style="color:red"></span></td>
<tr><td><?php echo translate('MaximumFPS') ?>&nbsp;(<?php echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_MAXFPS', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><input type="text" onclick="document.getElementById('newMonitor[MaxFPS]').innerHTML= ' CAUTION: See the help text'" name="newMonitor[MaxFPS]" value="<?php echo validHtmlStr($monitor->MaxFPS) ?>" size="5"/><span id="newMonitor[MaxFPS]" style="color:red"></span></td></tr> </tr>
<tr><td><?php echo translate('AlarmMaximumFPS') ?>&nbsp;(<?php echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_MAXFPS', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><input type="text" onclick="document.getElementById('newMonitor[AlarmMaxFPS]').innerHTML= ' CAUTION: See the help text'" name="newMonitor[AlarmMaxFPS]" value="<?php echo validHtmlStr($monitor->AlarmMaxFPS) ?>" size="5"/><span id="newMonitor[AlarmMaxFPS]" style="color:red"></span></td></tr> <tr>
<?php <td><?php echo translate('AlarmMaximumFPS') ?>&nbsp;(<?php echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_MAXFPS', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td>
} else { <td><input type="text" onclick="document.getElementById('newMonitor[AlarmMaxFPS]').innerHTML= ' CAUTION: See the help text'" name="newMonitor[AlarmMaxFPS]" value="<?php echo validHtmlStr($monitor->AlarmMaxFPS) ?>" size="5"/><span id="newMonitor[AlarmMaxFPS]" style="color:red"></span></td>
?> </tr>
<?php } else { ?>
<tr><td><?php echo translate('MaximumFPS') ?></td><td><input type="text" name="newMonitor[MaxFPS]" value="<?php echo validHtmlStr($monitor->MaxFPS) ?>" size="5"/></td></tr> <tr><td><?php echo translate('MaximumFPS') ?></td><td><input type="text" name="newMonitor[MaxFPS]" value="<?php echo validHtmlStr($monitor->MaxFPS) ?>" size="5"/></td></tr>
<tr><td><?php echo translate('AlarmMaximumFPS') ?></td><td><input type="text" name="newMonitor[AlarmMaxFPS]" value="<?php echo validHtmlStr($monitor->AlarmMaxFPS) ?>" size="5"/></td></tr> <tr><td><?php echo translate('AlarmMaximumFPS') ?></td><td><input type="text" name="newMonitor[AlarmMaxFPS]" value="<?php echo validHtmlStr($monitor->AlarmMaxFPS) ?>" size="5"/></td></tr>
<?php <?php
} }
if ( ZM_FAST_IMAGE_BLENDS ) if ( ZM_FAST_IMAGE_BLENDS ) {
{
?> ?>
<tr><td><?php echo translate('RefImageBlendPct') ?></td><td><select name="newMonitor[RefBlendPerc]"><?php foreach ( $fastblendopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->RefBlendPerc ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr> <tr><td><?php echo translate('RefImageBlendPct') ?></td><td><select name="newMonitor[RefBlendPerc]"><?php foreach ( $fastblendopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->RefBlendPerc ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
<tr><td><?php echo translate('AlmRefImageBlendPct') ?></td><td><select name="newMonitor[AlarmRefBlendPerc]"><?php foreach ( $fastblendopts_alarm as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->AlarmRefBlendPerc ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr> <tr><td><?php echo translate('AlmRefImageBlendPct') ?></td><td><select name="newMonitor[AlarmRefBlendPerc]"><?php foreach ( $fastblendopts_alarm as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->AlarmRefBlendPerc ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
@ -970,13 +978,14 @@ switch ( $tab )
} }
} }
?> ?>
</tbody> </tbody>
</table> </table>
<div id="contentButtons"> <div id="contentButtons">
<input type="submit" value="<?php echo translate('Save') ?>"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/><input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow()"/> <input type="submit" value="<?php echo translate('Save') ?>"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/><input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow()"/>
</div> </div>
</form>
</div> </form>
</div> </div>
</div>
</body> </body>
</html> </html>

View File

@ -115,7 +115,10 @@ if ( canEdit( 'Monitors' ) )
if ( canEdit( 'Monitors' ) ) if ( canEdit( 'Monitors' ) )
{ {
?> ?>
<div id="forceCancelAlarm"><a id="forceAlarmLink" href="#" onclick="cmdForceAlarm()" class="hidden"><?php echo translate('ForceAlarm') ?></a><a id="cancelAlarmLink" href="#" onclick="cmdCancelForcedAlarm()" class="hidden"><?php echo translate('CancelForcedAlarm') ?></a></div> <div id="forceCancelAlarm">
<a id="forceAlarmLink" href="#" onclick="cmdForceAlarm();"><?php echo translate('ForceAlarm') ?></a>
<a id="cancelAlarmLink" href="#" onclick="cmdCancelForcedAlarm();" class="hidden"><?php echo translate('CancelForcedAlarm') ?></a>
</div>
<?php <?php
} }
?> ?>

View File

@ -117,6 +117,11 @@ $newZone['Area'] = getPolyArea( $newZone['Points'] );
$selfIntersecting = isSelfIntersecting( $newZone['Points'] ); $selfIntersecting = isSelfIntersecting( $newZone['Points'] );
$focusWindow = true; $focusWindow = true;
$connkey = generateConnKey();
$streamSrc = '';
$streamMode = '';
# Have to do this here, because the .js.php references somethings figured out when generating the streamHTML
$StreamHTML = getStreamHTML( $monitor, $scale );
xhtmlHeaders(__FILE__, translate('Zone') ); xhtmlHeaders(__FILE__, translate('Zone') );
?> ?>
@ -210,13 +215,14 @@ xhtmlHeaders(__FILE__, translate('Zone') );
<div id="definitionPanel"> <div id="definitionPanel">
<div id="imagePanel"> <div id="imagePanel">
<div id="imageFrame" style="width: <?php echo reScale( $monitor->Width(), $scale ) ?>px; height: <?php echo reScale( $monitor->Height(), $scale ) ?>px;"> <div id="imageFrame" style="width: <?php echo reScale( $monitor->Width(), $scale ) ?>px; height: <?php echo reScale( $monitor->Height(), $scale ) ?>px;">
<?php echo getStreamHTML( $monitor, $scale ); ?> <?php $StreamHTML; ?>
<svg id="zoneSVG" class="zones" style="width: <?php echo reScale( $monitor->Width(), $scale ) ?>px; height: <?php echo reScale( $monitor->Height(), $scale ) ?>px;margin-top: -<?php echo $monitor->Height ?>px;background: none;"> <svg id="zoneSVG" class="zones" style="width: <?php echo reScale( $monitor->Width(), $scale ) ?>px; height: <?php echo reScale( $monitor->Height(), $scale ) ?>px;margin-top: -<?php echo $monitor->Height ?>px;background: none;">
<polygon id="zonePoly" points="<?php echo $zone['AreaCoords'] ?>" class="<?php echo $zone['Type'] ?>"/> <polygon id="zonePoly" points="<?php echo $zone['AreaCoords'] ?>" class="<?php echo $zone['Type'] ?>"/>
Sorry, your browser does not support inline SVG Sorry, your browser does not support inline SVG
</svg> </svg>
</div> </div>
</div> </div>
<div id="monitorState"><?php echo translate('State') ?>:&nbsp;<span id="stateValue"></span>&nbsp;-&nbsp;<span id="fpsValue"></span>&nbsp;fps</div>
<table id="zonePoints" cellspacing="0"> <table id="zonePoints" cellspacing="0">
<tbody> <tbody>
<tr> <tr>
@ -265,7 +271,7 @@ for ( $i = 0; $i < $pointCols; $i++ )
</tr> </tr>
</tbody> </tbody>
</table> </table>
<input type="submit" id="submitBtn" name="submitBtn" value="<?php echo translate('Save') ?>" onclick="return saveChanges( this )"<?php if (!canEdit( 'Monitors' ) || (false && $selfIntersecting)) { ?> disabled="disabled"<?php } ?>/><input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow()"/> <input id="pauseBtn" type="button" value="<?php echo translate('Pause') ?>" onclick="streamCmdPauseToggle()"/><input type="submit" id="submitBtn" name="submitBtn" value="<?php echo translate('Save') ?>" onclick="return saveChanges( this )"<?php if (!canEdit( 'Monitors' ) || (false && $selfIntersecting)) { ?> disabled="disabled"<?php } ?>/><input type="button" value="<?php echo translate('Cancel') ?>" onclick="refreshParentWindow(); closeWindow();"/>
</div> </div>
</form> </form>
</div> </div>

View File

@ -37,6 +37,8 @@ foreach( dbFetchAll( 'select * from Zones where MonitorId = ? order by Area desc
} }
} }
$connkey = generateConnKey();
xhtmlHeaders(__FILE__, translate('Zones') ); xhtmlHeaders(__FILE__, translate('Zones') );
?> ?>
<body> <body>
@ -51,7 +53,7 @@ xhtmlHeaders(__FILE__, translate('Zones') );
<?php <?php
foreach( array_reverse($zones) as $zone ) { foreach( array_reverse($zones) as $zone ) {
?> ?>
<polygon points="<?php echo $zone['AreaCoords'] ?>" class="<?php echo $zone['Type']?>" onclick="createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $monitor->Width ?>, <?php echo $monitor->Height ?> ); return( false );"/> <polygon points="<?php echo $zone['AreaCoords'] ?>" class="<?php echo $zone['Type']?>" onclick="streamCmdQuit( true ); createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $monitor->Width ?>, <?php echo $monitor->Height ?> ); return( false );"/>
<?php <?php
} // end foreach zone } // end foreach zone
?> ?>
@ -76,7 +78,7 @@ foreach( $zones as $zone )
{ {
?> ?>
<tr> <tr>
<td class="colName"><a href="#" onclick="createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $monitor->Width() ?>, <?php echo $monitor->Height() ?> ); return( false );"><?php echo $zone['Name'] ?></a></td> <td class="colName"><a href="#" onclick="streamCmdQuit( true ); createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $monitor->Width() ?>, <?php echo $monitor->Height() ?> ); return( false );"><?php echo $zone['Name'] ?></a></td>
<td class="colType"><?php echo $zone['Type'] ?></td> <td class="colType"><?php echo $zone['Type'] ?></td>
<td class="colUnits"><?php echo $zone['Area'] ?>&nbsp;/&nbsp;<?php echo sprintf( "%.2f", ($zone['Area']*100)/($monitor->Width()*$monitor->Height()) ) ?></td> <td class="colUnits"><?php echo $zone['Area'] ?>&nbsp;/&nbsp;<?php echo sprintf( "%.2f", ($zone['Area']*100)/($monitor->Width()*$monitor->Height()) ) ?></td>
<td class="colMark"><input type="checkbox" name="markZids[]" value="<?php echo $zone['Id'] ?>" onclick="configureDeleteButton( this );"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/></td> <td class="colMark"><input type="checkbox" name="markZids[]" value="<?php echo $zone['Id'] ?>" onclick="configureDeleteButton( this );"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/></td>

View File

@ -40,6 +40,7 @@ if ( !canView( 'Events' ) )
require_once('includes/Storage.php'); require_once('includes/Storage.php');
require_once('includes/Event.php'); require_once('includes/Event.php');
require_once('includes/Frame.php');
header( 'Content-type: image/jpeg' ); header( 'Content-type: image/jpeg' );
@ -67,6 +68,12 @@ if ( empty($_REQUEST['path']) )
$Event = new Event( $_REQUEST['eid'] ); $Event = new Event( $_REQUEST['eid'] );
$Storage = $Event->Storage(); $Storage = $Event->Storage();
$path = $Event->Relative_Path().'/'.sprintf("%'.0".ZM_EVENT_IMAGE_DIGITS.'d',$_REQUEST['fid']).'-capture.jpg'; $path = $Event->Relative_Path().'/'.sprintf("%'.0".ZM_EVENT_IMAGE_DIGITS.'d',$_REQUEST['fid']).'-capture.jpg';
} else {
# If we are only specifying fid, then the fid must be the primary key into the frames table. But when the event is specified, then it is the frame #
$Frame = new Frame( $_REQUEST['fid'] );
$Event = new Event( $Frame->EventId() );
$Storage = $Event->Storage();
$path = $Event->Relative_Path().'/'.sprintf("%'.0".ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-capture.jpg';
} }
} else { } else {
$errorText = "No image path"; $errorText = "No image path";