Merge branch 'storageareas' into tesla

This commit is contained in:
Isaac Connor 2017-11-22 11:41:11 -08:00
commit 9dd0f29e88
114 changed files with 4742 additions and 4552 deletions

View File

@ -30,6 +30,7 @@ env:
- OS=el DIST=7
- OS=fedora DIST=25
- OS=fedora DIST=26 DOCKER_REPO=knnniggett/packpack
- OS=fedora DIST=27 DOCKER_REPO=knnniggett/packpack
- OS=ubuntu DIST=trusty
- OS=ubuntu DIST=xenial
- OS=ubuntu DIST=trusty ARCH=i386

View File

@ -31,6 +31,8 @@ This is the recommended method to install ZoneMinder onto your system. ZoneMinde
- Fedora via [RPM Fusion](http://rpmfusion.org)
- OpenSuse via [third party repository](http://www.zoneminder.com/wiki/index.php/Installing_using_ZoneMinder_RPMs_for_SuSE)
- Mageia from their default repository
- Arch via the [AUR](https://aur.archlinux.org/packages/zoneminder/)
- Gentoo from their [default repository](https://packages.gentoo.org/packages/www-misc/zoneminder)
If a repository that hosts ZoneMinder packages is not available for your distro, then you are encouraged to build your own package, rather than build from source. While each distro is different in ways that set it apart from all the others, they are often similar enough to allow you to adapt another distro's package building instructions to your own.

View File

@ -195,6 +195,7 @@ CREATE TABLE `Events` (
`Frames` int(10) unsigned default NULL,
`AlarmFrames` int(10) unsigned default NULL,
`DefaultVideo` VARCHAR( 64 ) DEFAULT '' NOT NULL,
`SaveJPEGs` TINYINT,
`TotScore` int(10) unsigned NOT NULL default '0',
`AvgScore` smallint(5) unsigned default '0',
`MaxScore` smallint(5) unsigned default '0',
@ -384,6 +385,8 @@ CREATE TABLE `Monitors` (
`Deinterlacing` int(10) unsigned NOT NULL default '0',
`SaveJPEGs` TINYINT NOT NULL DEFAULT '3' ,
`VideoWriter` TINYINT NOT NULL DEFAULT '0',
`OutputCodec` enum('h264','mjpeg','mpeg1','mpeg2'),
`OutputContainer` enum('auto','mp4','mkv'),
`EncoderParameters` TEXT,
`RecordAudio` TINYINT NOT NULL DEFAULT '0',
`RTSPDescribe` tinyint(1) unsigned,
@ -428,9 +431,9 @@ CREATE TABLE `Monitors` (
`WebColour` varchar(32) NOT NULL default 'red',
`Exif` tinyint(1) unsigned NOT NULL default '0',
`Sequence` smallint(5) unsigned default NULL,
`Status` enum('Unknown','NotRunning','Running','NoSignal','Signal') NOT NULL default 'Unknown',
`zmcFPS` DECIMAL(5,2) NOT NULL default 0,
`zmaFPS` DECIMAL(5,2) NOT NULL default 0,
`Status` enum('Unknown','NotRunning','Running','NoSignal','Signal') NOT NULL default 'Unknown',
`CaptureFPS` DECIMAL(10,2) NOT NULL default 0,
`AnalysisFPS` DECIMAL(5,2) NOT NULL default 0,
PRIMARY KEY (`Id`)
) ENGINE=@ZM_MYSQL_ENGINE@;
@ -606,13 +609,14 @@ CREATE TABLE `Storage` (
`Path` varchar(64) NOT NULL default '',
`Name` varchar(64) NOT NULL default '',
`Type` enum('local','s3fs') NOT NULL default 'local',
`DiskSpace` bigint unsigned default NULL,
PRIMARY KEY (`Id`)
) ENGINE=@ZM_MYSQL_ENGINE@;
--
-- Create a default storage location
--
insert into Storage VALUES (NULL, '/var/cache/zoneminder/events', 'Default', 'local' );
insert into Storage VALUES (NULL, '/var/cache/zoneminder/events', 'Default', 'local', NULL );
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;

View File

@ -67,3 +67,4 @@ SET @s = (SELECT IF(
PREPARE stmt FROM @s;
EXECUTE stmt;

26
db/zm_update-1.31.13.sql Normal file
View File

@ -0,0 +1,26 @@
ALTER TABLE `Monitors` MODIFY `OutputCodec` enum('h264','mjpeg','mpeg1','mpeg2') default 'h264';
ALTER TABLE `Monitors` MODIFY `OutputContainer` enum('auto','mp4','mkv') default 'auto';
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Events'
AND column_name = 'SaveJPEGs'
) > 0,
"SELECT 'Column SaveJPEGs already exists in Events'",
"ALTER TABLE `Events` ADD `SaveJPEGs` TINYINT AFTER `DefaultVideo`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Storage'
AND column_name = 'DiskSpace'
) > 0,
"SELECT 'Column DiskSpace already exists in Events'",
"ALTER TABLE `Storage` ADD `DiskSpace` bigint unsigned default NULL AFTER `Type`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

View File

@ -16,3 +16,5 @@ SET @s = (SELECT IF(
PREPARE stmt FROM @s;
EXECUTE stmt;
INSERT INTO `Controls` VALUES (28,'Floureon 1080P','Ffmpeg','Floureon',0,0,0,1,0,0,0,1,1,18,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,0,1,1,1,0,0,0,1,1,0,0,0,0,1,1,8,0,0,1,0,0,0,0,1,1,8,0,0,0,0);

View File

@ -27,9 +27,7 @@ override_dh_auto_configure:
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
-DZM_DIR_IMAGES="/var/cache/zoneminder/images" \
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms" \
-DZM_NO_CURL=1 \
-DZM_NO_LIBVLC=1
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
override_dh_clean:
dh_clean $(MANPAGES1)

View File

@ -17,23 +17,16 @@ if [ "$1" = "configure" ]; then
a2enmod cgi
fi
# Do this every time the package is installed or upgraded
# Ensure zoneminder is stopped
deb-systemd-invoke stop zoneminder.service || exit $?
# Ensure zoneminder is stopped
deb-systemd-invoke stop zoneminder.service || exit $?
if [ "$ZM_DB_HOST" = "localhost" ]; then
if [ -e "/etc/init.d/mysql" ]; then
# Do this every time the package is installed or upgraded
# Ensure zoneminder is stopped
deb-systemd-invoke stop zoneminder.service || exit $?
#
# 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...

View File

@ -15,9 +15,11 @@ achieve the same result by running:
::
tasksel install lamp-server
sudo tasksel install lamp-server
During installation it will ask you to set up a master/root password for the MySQL.
Installing LAMP is not ZoneMinder specific so you will find plenty of resources to
guide you with a quick search.
**Step 1:** Either run commands in this install using sudo or use the below to become root
::

View File

@ -115,7 +115,7 @@ BEGIN {
, $Config{ZM_DB_USER}
, $Config{ZM_DB_PASS}
) or croak( "Can't connect to db" );
my $sql = 'select * from Config';
my $sql = 'SELECT Name,Value FROM Config';
my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() );
while( my $config = $sth->fetchrow_hashref() ) {

View File

@ -0,0 +1,390 @@
# Modified on 2017-11-17 by Ognyan Bankov
# ==========================================================================
#
# ZoneMinder Floureon 1080p IP Control Protocol Module, $Date: 2017-11-17 09:20:00 +0000 $, $Revision: 0001 $
# Copyright (C) 2017 Ognyan Bankov
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# ==========================================================================
#
# This module contains the implementation of the Floureon 1080p 18x (Model: BT-HD54F) IP camera control
# protocol. It should work with other Floureon cameras too.
#
#
package MyAgent;
use base 'LWP::UserAgent';
package ZoneMinder::Control::Floureon;
use 5.006;
use strict;
use warnings;
require ZoneMinder::Base;
require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
our $VERSION = $ZoneMinder::Base::VERSION;
# ==========================================================================
#
# Floureon IP Control Protocol
#
# ==========================================================================
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep );
sub new
{
my $class = shift;
my $id = shift;
my $self = ZoneMinder::Control->new( $id );
my $logindetails = "";
bless( $self, $class );
srand( time() );
return $self;
}
our $AUTOLOAD;
sub AUTOLOAD
{
my $self = shift;
my $class = ref($self) || croak( "$self not object" );
my $name = $AUTOLOAD;
$name =~ s/.*://;
if ( exists($self->{$name}) )
{
return( $self->{$name} );
}
Fatal( "Can't access $name member of object of class $class" );
}
our $stop_command;
sub open
{
my $self = shift;
$self->loadMonitor();
$self->{ua} = MyAgent->new;
$self->{ua}->agent( "ZoneMinder Control Agent/" );
$self->{state} = 'open';
}
sub close
{
my $self = shift;
$self->{state} = 'closed';
}
sub printMsg
{
my $self = shift;
my $msg = shift;
my $msg_len = length($msg);
Debug( $msg."[".$msg_len."]" );
}
sub sendCmd
{
my $self = shift;
my $cmd = shift;
my $result = undef;
printMsg( $cmd, "Tx" );
my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd"."&".$self->{Monitor}->{ControlDevice});
print ("Sending $req\n");
my $res = $self->{ua}->request($req);
if ( $res->is_success )
{
$result = !undef;
}
else
{
Error( "Error REALLY check failed:'".$res->status_line()."'" );
Error ("Cmd:".$req);
}
return( $result );
}
sub reset
{
my $self = shift;
Debug( "Camera Reset" );
my $cmd = "reboot.cgi?";
$self->sendCmd( $cmd );
}
# PP - in all move operations, added auto stop after timeout
#Up Arrow
sub moveConUp
{
my $self = shift;
my $params = shift;
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Up" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=1&PanSpeed=6&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Down Arrow
sub moveConDown
{
my $self = shift;
my $params = shift;
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Down" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=2&PanSpeed=6&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Left Arrow
sub moveConLeft
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
Debug( "Move Left" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=3&PanSpeed=$panspeed&TiltSpeed=6";
$self->sendCmd( $cmd );
$self->autoStop($panspeed);
}
#Right Arrow
sub moveConRight
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
Debug( "Move Right" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=4&PanSpeed=$panspeed&TiltSpeed=6";
$self->sendCmd( $cmd );
$self->autoStop($panspeed);
}
#Diagonally Up Right Arrow
sub moveConUpRight
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Up Right" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=7&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Diagonally Down Right Arrow
sub moveConDownRight
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Down Right" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=8&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Diagonally Up Left Arrow
sub moveConUpLeft
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Up Left" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=5&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Diagonally Down Left Arrow
sub moveConDownLeft
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Down Left" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=6&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Stop
sub moveStop
{
my $self = shift;
Debug( "Move Stop" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Stop=0";
$self->sendCmd( $cmd );
}
sub zoomConTele
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Zoom=1";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub zoomConWide
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Zoom=0";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub focusConNear
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Focus=1";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub focusConFar
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Focus=0";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub irisConOpen
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Iris=1";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub irisConClose
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Iris=0";
$self->sendCmd( $cmd );
$self->autoStop();
}
#Set preset
sub presetSet
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&PresetNumber=1&Preset=0";
$self->sendCmd( $cmd );
}
#Goto preset
sub presetGoto
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&PresetNumber=1&Preset=1";
$self->sendCmd( $cmd );
}
sub autoStop
{
my $self = shift;
my $timeout = shift;
if ($timeout)
{
if ($timeout > 1) {
usleep(100000*$timeout);
}
}
Debug( "Auto Stop" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Stop=0";
$self->sendCmd( $cmd );
}
1;
__END__
=head1 Floureon
ZoneMinder::Database - Perl extension for Floureon 1080P
=head1 SYNOPSIS
Control script for Floureon 1080P IP camera
=head1 DESCRIPTION
When setuping you monitor in the "Control" tab:
1. Select "Control type": Floureon 1080P
2. Leave "Control device" empty
3. Fill "Control Address" like username:password@ip/domain. Example: admin:admin123@192.168.1.110
=head2 EXPORT
None by default.
=head1 SEE ALSO
=head1 AUTHOR
Ognyan Bankov, E<lt>ogibankov@gmail.comE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2017 Ognyan Bankov
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.3 or,
at your option, any later version of Perl 5 you may have available.
=cut

View File

@ -390,7 +390,7 @@ sub age {
sub DiskSpace {
if ( @_ > 1 ) {
Debug("Cleared DiskSpace, was $_[0]{DiskSpace}");
Debug("Cleared DiskSpace, was $_[0]{DiskSpace}") if $_[0]{DiskSpace};
$_[0]{DiskSpace} = $_[1];
}
if ( ! defined $_[0]{DiskSpace} ) {

View File

@ -21,34 +21,6 @@
#
# ==========================================================================
=head1 NAME
zmaudit.pl - ZoneMinder event file system and database consistency checker
=head1 SYNOPSIS
zmaudit.pl [-r,-report|-i,-interactive]
=head1 DESCRIPTION
This script checks for consistency between the event filesystem and
the database. If events are found in one and not the other they are
deleted (optionally). Additionally any monitor event directories that
do not correspond to a database monitor are similarly disposed of.
However monitors in the database that don't have a directory are left
alone as this is valid if they are newly created and have no events
yet.
=head1 OPTIONS
-c, --continuous - Run continuously
-i, --interactive - Ask before applying any changes
-m, --monitor_id - Restrict zmaudit actions to events pertaining to the specified monitor id
-r, --report - Just report don't actually do anything
-v, --version - Print the installed version of ZoneMinder
=cut
use strict;
use bytes;
@ -81,6 +53,7 @@ use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|)
? $Config{ZM_DIR_EVENTS}
: ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS})
;
use constant ZM_AUDIT_PID => '@ZM_RUNDIR@/zmaudit.pid';
$| = 1;
@ -118,6 +91,17 @@ if ( ! exists $Config{ZM_AUDIT_MIN_AGE} ) {
Fatal('ZM_AUDIT_MIN_AGE is not set in config.');
}
if ( -e ZM_AUDIT_PID ) {
Fatal('zmaudit.pl appears to already be running. If not, please delete ' . ZM_AUDIT_PID );
} else {
if ( open( my $PID, '>', ZM_AUDIT_PID ) ) {
print( $PID $$ );
close( $PID );
} else {
Error( "Can't open pid file at " . ZM_PID );
}
}
my $dbh = zmDbConnect();
require ZoneMinder::Monitor;
@ -598,6 +582,7 @@ Debug("Event $db_event is not in fs.");
sleep( $Config{ZM_AUDIT_CHECK_INTERVAL} ) if $continuous;
};
unlink ZM_AUDIT_PID;
exit( 0 );
sub aud_print {
@ -688,3 +673,30 @@ sub delete_empty_directories {
1;
__END__
=head1 NAME
zmaudit.pl - ZoneMinder event file system and database consistency checker
=head1 SYNOPSIS
zmaudit.pl [-r,-report|-i,-interactive]
=head1 DESCRIPTION
This script checks for consistency between the event filesystem and
the database. If events are found in one and not the other they are
deleted (optionally). Additionally any monitor event directories that
do not correspond to a database monitor are similarly disposed of.
However monitors in the database that don't have a directory are left
alone as this is valid if they are newly created and have no events
yet.
=head1 OPTIONS
-c, --continuous - Run continuously
-i, --interactive - Ask before applying any changes
-r, --report - Just report don't actually do anything
-v, --version - Print the installed version of ZoneMinder
=cut

View File

@ -21,20 +21,6 @@
#
# ==========================================================================
=head1 NAME
zmpkg.pl - ZoneMinder Package Control Script
=head1 SYNOPSIS
zmpkg.pl {start|stop|restart|status|logrot|'state'|version}
=head1 DESCRIPTION
This script is used to start and stop the ZoneMinder package primarily to
allow command line control for automatic restart on reboot (see zm script)
=cut
use strict;
use bytes;
@ -61,48 +47,41 @@ logInit();
my $command = $ARGV[0]||'';
if ( $command eq 'version' ) {
print ZoneMinder::Base::ZM_VERSION . "\n";
exit(0);
print ZoneMinder::Base::ZM_VERSION . "\n";
exit(0);
}
my $state;
my $dbh;
if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ )
{
if ( $command )
{
$dbh = zmDbConnect();
# Check to see if it's a valid run state
my $sql = 'select * from States where Name = ?';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $command )
or Fatal( "Can't execute: ".$sth->errstr() );
if ( $state = $sth->fetchrow_hashref() )
{
$state->{Name} = $command;
$state->{Definitions} = [];
foreach( split( /,/, $state->{Definition} ) )
{
my ( $id, $function, $enabled ) = split( /:/, $_ );
push( @{$state->{Definitions}},
{ Id=>$id, Function=>$function, Enabled=>$enabled }
);
}
$store_state=$command; # PP - Remember the name that was passed to search in DB
$command = 'state';
}
else
{
$command = undef;
}
}
if ( !$command )
{
pod2usage(-exitstatus => -1);
if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) {
if ( $command ) {
$dbh = zmDbConnect();
# Check to see if it's a valid run state
my $sql = 'SELECT * FROM States WHERE Name=?';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $command )
or Fatal( "Can't execute: ".$sth->errstr() );
if ( $state = $sth->fetchrow_hashref() ) {
$state->{Name} = $command;
$state->{Definitions} = [];
foreach( split( /,/, $state->{Definition} ) ) {
my ( $id, $function, $enabled ) = split( /:/, $_ );
push( @{$state->{Definitions}},
{ Id=>$id, Function=>$function, Enabled=>$enabled }
);
}
$store_state=$command; # PP - Remember the name that was passed to search in DB
$command = 'state';
} else {
$command = undef;
}
}
if ( !$command ) {
pod2usage(-exitstatus => -1);
}
}
$dbh = zmDbConnect() if ! $dbh;
# PP - Sane state check
@ -110,324 +89,297 @@ isActiveSanityCheck();
# Move to the right place
chdir( $Config{ZM_PATH_WEB} )
or Fatal( "Can't chdir to '".$Config{ZM_PATH_WEB}."': $!" );
or Fatal( "Can't chdir to '".$Config{ZM_PATH_WEB}."': $!" );
my $dbg_id = "";
my $dbg_id = '';
Info( "Command: $command\n" );
Info( "Command: $command\n" );
my $retval = 0;
my $retval = 0;
if ( $command eq "state" )
{
if ( $command eq 'state' ) {
Info( "Updating DB: $state->{Name}\n" );
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=? ORDER BY Id ASC' : 'SELECT * FROM Monitors ORDER BY Id ASC';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID}: () )
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() )
{
foreach my $definition ( @{$state->{Definitions}} )
{
if ( $monitor->{Id} =~ /^$definition->{Id}$/ )
{
$monitor->{NewFunction} = $definition->{Function};
$monitor->{NewEnabled} = $definition->{Enabled};
}
}
#next if ( !$monitor->{NewFunction} );
$monitor->{NewFunction} = 'None'
if ( !$monitor->{NewFunction} );
$monitor->{NewEnabled} = 0
if ( !$monitor->{NewEnabled} );
if ( $monitor->{Function} ne $monitor->{NewFunction}
|| $monitor->{Enabled} ne $monitor->{NewEnabled}
)
{
my $sql = "update Monitors set Function = ?, Enabled = ? where Id = ?";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id} )
or Fatal( "Can't execute: ".$sth->errstr() );
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) {
foreach my $definition ( @{$state->{Definitions}} ) {
if ( $monitor->{Id} =~ /^$definition->{Id}$/ ) {
$monitor->{NewFunction} = $definition->{Function};
$monitor->{NewEnabled} = $definition->{Enabled};
}
}
#next if ( !$monitor->{NewFunction} );
$monitor->{NewFunction} = 'None'
if ( !$monitor->{NewFunction} );
$monitor->{NewEnabled} = 0
if ( !$monitor->{NewEnabled} );
if ( $monitor->{Function} ne $monitor->{NewFunction}
|| $monitor->{Enabled} ne $monitor->{NewEnabled}
) {
my $sql = 'UPDATE Monitors SET Function=?, Enabled=? WHERE Id=?';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id} )
or Fatal( "Can't execute: ".$sth->errstr() );
}
}
$sth->finish();
# PP - Now mark a specific state as active
# PP - Now mark a specific state as active
resetStates();
Info ("Marking $store_state as Enabled");
$sql = "update States set IsActive = '1' where Name = ?";
$sql = "UPDATE States SET IsActive = '1' WHERE Name = ?";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute( $store_state )
or Fatal( "Can't execute: ".$sth->errstr() );
or Fatal( "Can't execute: ".$sth->errstr() );
# PP - zero out other states isActive
$command = "restart";
}
# PP - zero out other states isActive
$command = 'restart';
}
# Check if we are running systemd and if we have been called by the system
if ( $command =~ /^(start|stop|restart)$/ )
{
# We have to detaint to keep perl from complaining
$command = $1;
if ( $command =~ /^(start|stop|restart)$/ ) {
# We have to detaint to keep perl from complaining
$command = $1;
if ( systemdRunning() && !calledBysystem() ) {
qx(@BINDIR@/zmsystemctl.pl $command);
$command = "";
}
if ( systemdRunning() && !calledBysystem() ) {
qx(@BINDIR@/zmsystemctl.pl $command);
$command = '';
}
}
if ( $command =~ /^(?:stop|restart)$/ )
{
my $status = runCommand( "zmdc.pl check" );
if ( $command =~ /^(?:stop|restart)$/ ) {
my $status = runCommand('zmdc.pl check');
if ( $status eq "running" )
{
runCommand( "zmdc.pl shutdown" );
zmMemTidy();
}
else
{
$retval = 1;
}
if ( $status eq 'running' ) {
runCommand('zmdc.pl shutdown');
zmMemTidy();
} else {
$retval = 1;
}
}
#runCommand( "zmupdate.pl -f" );
if ( $command =~ /^(?:start|restart)$/ )
{
my $status = runCommand( "zmdc.pl check" );
if ( $command =~ /^(?:start|restart)$/ ) {
my $status = runCommand('zmdc.pl check');
if ( $status eq "stopped" )
{
if ( $Config{ZM_DYN_DB_VERSION}
and ( $Config{ZM_DYN_DB_VERSION} ne ZM_VERSION )
)
{
Fatal( "Version mismatch, system is version ".ZM_VERSION
.", database is ".$Config{ZM_DYN_DB_VERSION}
.", please run zmupdate.pl to update."
);
exit( -1 );
}
if ( $status eq 'stopped' ) {
if ( $Config{ZM_DYN_DB_VERSION}
and ( $Config{ZM_DYN_DB_VERSION} ne ZM_VERSION )
) {
Fatal( 'Version mismatch, system is version '.ZM_VERSION
.', database is '.$Config{ZM_DYN_DB_VERSION}
.', please run zmupdate.pl to update.'
);
exit( -1 );
}
# Recreate the temporary directory if it's been wiped
verifyFolder("@ZM_TMPDIR@");
# Recreate the temporary directory if it's been wiped
verifyFolder('@ZM_TMPDIR@');
# Recreate the run directory if it's been wiped
verifyFolder("@ZM_RUNDIR@");
# Recreate the run directory if it's been wiped
verifyFolder('@ZM_RUNDIR@');
# Recreate the sock directory if it's been wiped
verifyFolder("@ZM_SOCKDIR@");
# Recreate the sock directory if it's been wiped
verifyFolder('@ZM_SOCKDIR@');
zmMemTidy();
runCommand( "zmdc.pl startup" );
zmMemTidy();
runCommand('zmdc.pl startup');
if ( $Config{ZM_SERVER_ID} ) {
Info( "Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n");
if ( $Config{ZM_SERVER_ID} ) {
Info("Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n");
} else {
Info('Single server configuration detected. Starting up services.');
}
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) {
if ( $monitor->{Function} ne 'None' ) {
if ( $monitor->{Type} eq 'Local' ) {
runCommand( "zmdc.pl start zmc -d $monitor->{Device}" );
} else {
Info( "Single server configuration detected. Starting up services." );
runCommand( "zmdc.pl start zmc -m $monitor->{Id}" );
}
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() )
{
if ( $monitor->{Function} ne 'None' )
{
if ( $monitor->{Type} eq 'Local' )
{
runCommand( "zmdc.pl start zmc -d $monitor->{Device}" );
}
else
{
runCommand( "zmdc.pl start zmc -m $monitor->{Id}" );
}
if ( $monitor->{Function} ne 'Monitor' )
{
runCommand( "zmdc.pl start zma -m $monitor->{Id}" );
}
if ( $Config{ZM_OPT_CONTROL} )
{
if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' )
{
if ( $monitor->{Controllable} && $monitor->{TrackMotion} )
{
runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" );
}
}
}
if ( $monitor->{Function} ne 'Monitor' ) {
runCommand( "zmdc.pl start zma -m $monitor->{Id}" );
}
if ( $Config{ZM_OPT_CONTROL} ) {
if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' ) {
if ( $monitor->{Controllable} && $monitor->{TrackMotion} ) {
runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" );
}
}
}
$sth->finish();
}
}
$sth->finish();
# This is now started unconditionally
runCommand( "zmdc.pl start zmfilter.pl" );
if ( $Config{ZM_RUN_AUDIT} )
{
runCommand( "zmdc.pl start zmaudit.pl -c" );
}
if ( $Config{ZM_OPT_TRIGGERS} )
{
runCommand( "zmdc.pl start zmtrigger.pl" );
}
if ( $Config{ZM_OPT_X10} )
{
runCommand( "zmdc.pl start zmx10.pl -c start" );
}
runCommand( "zmdc.pl start zmwatch.pl" );
if ( $Config{ZM_CHECK_FOR_UPDATES} )
{
runCommand( "zmdc.pl start zmupdate.pl -c" );
}
if ( $Config{ZM_TELEMETRY_DATA} )
{
runCommand( "zmdc.pl start zmtelemetry.pl" );
}
# This is now started unconditionally
runCommand('zmdc.pl start zmfilter.pl');
if ( $Config{ZM_RUN_AUDIT} ) {
runCommand('zmdc.pl start zmaudit.pl -c');
}
else
{
$retval = 1;
if ( $Config{ZM_OPT_TRIGGERS} ) {
runCommand('zmdc.pl start zmtrigger.pl');
}
if ( $Config{ZM_OPT_X10} ) {
runCommand('zmdc.pl start zmx10.pl -c start');
}
runCommand('zmdc.pl start zmwatch.pl');
if ( $Config{ZM_CHECK_FOR_UPDATES} ) {
runCommand('zmdc.pl start zmupdate.pl -c');
}
if ( $Config{ZM_TELEMETRY_DATA} ) {
runCommand('zmdc.pl start zmtelemetry.pl');
}
} else {
$retval = 1;
}
}
if ( $command eq "status" )
{
my $status = runCommand( "zmdc.pl check" );
if ( $command eq 'status' ) {
my $status = runCommand('zmdc.pl check');
print( STDOUT $status."\n" );
}
if ( $command eq "logrot" )
{
runCommand( "zmdc.pl logrot" );
print( STDOUT $status."\n" );
} elsif ( $command eq 'logrot' ) {
runCommand('zmdc.pl logrot');
}
exit( $retval );
# PP - Make sure isActive is on and only one
sub isActiveSanityCheck
{
sub isActiveSanityCheck {
Info ("Sanity checking States table...");
$dbh = zmDbConnect() if ! $dbh;
# PP - First, make sure default exists and there is only one
my $sql = "select Name from States where Name = 'default'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
Info ('Sanity checking States table...');
$dbh = zmDbConnect() if ! $dbh;
if ($sth->rows != 1) # PP - no row, or too many rows. Either case is an error
{
Info( "Fixing States table - either no default state or duplicate default states" );
$sql = "delete from States where Name = 'default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
$sql = "insert into States (Name,Definition,IsActive) VALUES ('default','','1');";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
# PP - First, make sure default exists and there is only one
my $sql = "SELECT Name FROM States WHERE Name='default'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
if ($sth->rows != 1) {
# PP - no row, or too many rows. Either case is an error
Info( 'Fixing States table - either no default state or duplicate default states' );
$sql = "DELETE FROM States WHERE Name='default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
$sql = "INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
# PP - Now make sure no two states have IsActive=1
$sql = "select Name from States where IsActive = '1'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
# PP - Now make sure no two states have IsActive=1
$sql = "SELECT Name FROM States WHERE IsActive = '1'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
if ( $sth->rows != 1 )
{
Info( "Fixing States table so only one run state is active" );
resetStates();
$sql = "update States set IsActive='1' WHERE Name='default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
if ( $sth->rows != 1 ) {
Info( 'Fixing States table so only one run state is active' );
resetStates();
$sql = "UPDATE States SET IsActive='1' WHERE Name='default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
}
# PP - zeroes out isActive for all states
sub resetStates
{
$dbh = zmDbConnect() if ! $dbh;
my $sql = "update States set IsActive = '0'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
sub resetStates {
$dbh = zmDbConnect() if ! $dbh;
my $sql = "UPDATE States SET IsActive='0'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
sub systemdRunning
{
my $result = 0;
sub systemdRunning {
my $result = 0;
my $output = qx(ps -o comm="" -p 1);
chomp( $output );
my $output = qx(ps -o comm="" -p 1);
chomp( $output );
if ($output =~ /systemd/) {
$result = 1;
if ( $output =~ /systemd/ ) {
$result = 1;
}
return $result;
}
sub calledBysystem {
my $result = 0;
my $ppid = getppid();
my $output = qx(ps -o comm="" -p $ppid);
chomp( $output );
if ($output =~ /^(?:systemd|init)$/) {
$result = 1;
}
return $result;
}
sub verifyFolder {
my $folder = shift;
# Recreate the temporary directory if it's been wiped
if ( !-e $folder ) {
Debug( "Recreating directory '$folder'" );
mkdir( $folder, 0774 )
or Fatal( "Can't create missing temporary directory '$folder': $!" );
my ( $runName ) = getpwuid( $> );
if ( $runName ne $Config{ZM_WEB_USER} ) {
# Not running as web user, so should be root in which case
# chown the directory
my ( $webName, $webPass, $webUid, $webGid ) = getpwnam( $Config{ZM_WEB_USER} )
or Fatal( "Can't get user details for web user '"
.$Config{ZM_WEB_USER}."': $!"
);
chown( $webUid, $webGid, "$folder" )
or Fatal( "Can't change ownership of directory '$folder' to '"
.$Config{ZM_WEB_USER}.":".$Config{ZM_WEB_GROUP}."': $!"
);
}
return $result;
}
}
sub calledBysystem
{
my $result = 0;
my $ppid = getppid();
my $output = qx(ps -o comm="" -p $ppid);
chomp( $output );
if ($output =~ /^(?:systemd|init)$/) {
$result = 1;
}
return $result;
}
sub verifyFolder
{
my $folder = shift;
# Recreate the temporary directory if it's been wiped
if ( !-e $folder )
{
Debug( "Recreating directory '$folder'" );
mkdir( "$folder", 0774 )
or Fatal( "Can't create missing temporary directory '$folder': $!" );
my ( $runName ) = getpwuid( $> );
if ( $runName ne $Config{ZM_WEB_USER} )
{
# Not running as web user, so should be root in which case
# chown the directory
my ( $webName, $webPass, $webUid, $webGid ) = getpwnam( $Config{ZM_WEB_USER} )
or Fatal( "Can't get user details for web user '"
.$Config{ZM_WEB_USER}."': $!"
);
chown( $webUid, $webGid, "$folder" )
or Fatal( "Can't change ownership of directory '$folder' to '"
.$Config{ZM_WEB_USER}.":".$Config{ZM_WEB_GROUP}."': $!"
);
}
}
}
1;
__END__
=head1 NAME
zmpkg.pl - ZoneMinder Package Control Script
=head1 SYNOPSIS
zmpkg.pl {start|stop|restart|status|logrot|'state'|version}
=head1 DESCRIPTION
This script is used to start and stop the ZoneMinder package primarily to
allow command line control for automatic restart on reboot (see zm script)
=cut

View File

@ -55,6 +55,7 @@ use constant START_DELAY => 30; # To give everything else time to start
@EXTRA_PERL_LIB@
use ZoneMinder;
use ZoneMinder::Storage;
use POSIX;
use DBI;
use autouse 'Data::Dumper'=>qw(Dumper);
@ -175,6 +176,14 @@ while( 1 ) {
# Prevent open handles building up if we have connect to shared memory
zmMemInvalidate( $monitor ); # Close our file handle to the zmc process we are about to end
} # end foreach monitor
my $diskspace_sql = 'UPDATE Storage SET DiskSpace =(SELECT SUM(DiskSpace) FROM Events WHERE StorageId=? AND DiskSpace IS NOT NULL)';
my $diskspace_sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
foreach my $Storage ( ZoneMinder::Storage->find() ) {
Error("Updating disk space for $$Storage{Name}");
$diskspace_sth->execute( $$Storage{Id} ) or Error( "Can't execute: ".$diskspace_sth->errstr() );
}
$diskspace_sth->finish();
sleep( $Config{ZM_WATCH_CHECK_INTERVAL} );
} # end while (1)

View File

@ -1,25 +0,0 @@
snprintf( swap_path, sizeof(swap_path), "%s/zmswap-m%d/zmswap-q%06d", staticConfig.PATH_SWAP.c_str(), monitor->Id(), connkey );
int len = snprintf(NULL, 0, "/zmswap-m%d", monitor->Id());
int swap_path_length = strlen(staticConfig.PATH_SWAP.c_str()) + snprintf(NULL, 0, "/zmswap-m%d", monitor->Id() ) + snprintf(NULL, 0, "/zmswap-q%06d", connkey ) + 1; // +1 for NULL terminator
if ( connkey && playback_buffer > 0 ) {
if ( swap_path_length + max_swap_len_suffix > PATH_MAX ) {
Error( "Swap Path is too long. %d > %d ", swap_path_length+max_swap_len_suffix, PATH_MAX );
} else {
swap_path = (char *)malloc( swap_path_length+max_swap_len_suffix );
Debug( 3, "Checking swap image path %s", staticConfig.PATH_SWAP.c_str() );
strncpy( swap_path, staticConfig.PATH_SWAP.c_str(), swap_path_length );
if ( checkSwapPath( swap_path, false ) ) {
snprintf( &(swap_path[swap_path_length]), max_swap_len_suffix, "/zmswap-m%d", monitor->Id() );
if ( checkSwapPath( swap_path, true ) ) {
snprintf( &(swap_path[swap_path_length]), max_swap_len_suffix, "/zmswap-q%06d", connkey );
if ( checkSwapPath( swap_path, true ) ) {
buffered_playback = true;
}
}
}

View File

@ -43,7 +43,7 @@ public:
inline Box()
{
}
inline Box( int p_size ) : lo( 0, 0 ), hi ( p_size-1, p_size-1 ), size( Coord::Range( hi, lo ) ) { }
explicit inline Box( int p_size ) : lo( 0, 0 ), hi ( p_size-1, p_size-1 ), size( Coord::Range( hi, lo ) ) { }
inline Box( int p_x_size, int p_y_size ) : lo( 0, 0 ), hi ( p_x_size-1, p_y_size-1 ), size( Coord::Range( hi, lo ) ) { }
inline Box( int lo_x, int lo_y, int hi_x, int hi_y ) : lo( lo_x, lo_y ), hi( hi_x, hi_y ), size( Coord::Range( hi, lo ) ) { }
inline Box( const Coord &p_lo, const Coord &p_hi ) : lo( p_lo ), hi( p_hi ), size( Coord::Range( hi, lo ) ) { }

View File

@ -36,7 +36,7 @@ protected:
public:
Buffer() : mStorage( 0 ), mAllocation( 0 ), mSize( 0 ), mHead( 0 ), mTail( 0 ) {
}
Buffer( unsigned int pSize ) : mAllocation( pSize ), mSize( 0 ) {
explicit Buffer( unsigned int pSize ) : mAllocation( pSize ), mSize( 0 ) {
mHead = mStorage = new unsigned char[mAllocation];
mTail = mHead;
}

View File

@ -45,6 +45,7 @@ Camera::Camera( unsigned int p_monitor_id, SourceType p_type, unsigned int p_wid
} else if(colours == ZM_COLOUR_RGB24 && ((imagesize % 64) != 0 || (imagesize % 12) != 0)) {
Fatal("Image size is not multiples of 12 and 64");
}
monitor = NULL;
}
Camera::~Camera() {

View File

@ -42,11 +42,10 @@
#include <sys/filio.h> // define FIONREAD
#endif
int CommsBase::readV( int iovcnt, /* const void *, int, */ ... )
{
int CommsBase::readV( int iovcnt, /* const void *, int, */ ... ) {
va_list arg_ptr;
//struct iovec iov[iovcnt];
struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt );
struct iovec iov[iovcnt];
//struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt );
va_start( arg_ptr, iovcnt );
for ( int i = 0; i < iovcnt; i++ )
@ -62,11 +61,10 @@ int CommsBase::readV( int iovcnt, /* const void *, int, */ ... )
return( nBytes );
}
int CommsBase::writeV( int iovcnt, /* const void *, int, */ ... )
{
int CommsBase::writeV( int iovcnt, /* const void *, int, */ ... ) {
va_list arg_ptr;
//struct iovec iov[iovcnt];
struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt );
struct iovec iov[iovcnt];
//struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt );
va_start( arg_ptr, iovcnt );
for ( int i = 0; i < iovcnt; i++ )
@ -761,10 +759,10 @@ void Select::clearTimeout()
void Select::calcMaxFd()
{
mMaxFd = -1;
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ )
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); ++iter )
if ( (*iter)->getMaxDesc() > mMaxFd )
mMaxFd = (*iter)->getMaxDesc();
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ )
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); ++iter )
if ( (*iter)->getMaxDesc() > mMaxFd )
mMaxFd = (*iter)->getMaxDesc();
}
@ -839,12 +837,12 @@ int Select::wait()
mReadable.clear();
FD_ZERO(&rfds);
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ )
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); ++iter )
FD_SET((*iter)->getReadDesc(),&rfds);
mWriteable.clear();
FD_ZERO(&wfds);
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ )
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); ++iter )
FD_SET((*iter)->getWriteDesc(),&wfds);
int nFound = select( mMaxFd+1, &rfds, &wfds, NULL, selectTimeout );
@ -858,10 +856,10 @@ int Select::wait()
}
else
{
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ )
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); ++iter )
if ( FD_ISSET((*iter)->getReadDesc(),&rfds) )
mReadable.push_back( *iter );
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ )
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); ++iter )
if ( FD_ISSET((*iter)->getWriteDesc(),&rfds) )
mWriteable.push_back( *iter );
}

View File

@ -37,26 +37,20 @@
#include <netinet/in.h>
#endif
class CommsException : public Exception
{
class CommsException : public Exception {
public:
CommsException( const std::string &message ) : Exception( message )
{
}
explicit CommsException( const std::string &message ) : Exception( message ) { }
};
class CommsBase
{
class CommsBase {
protected:
const int &mRd;
const int &mWd;
protected:
CommsBase( int &rd, int &wd ) : mRd( rd ), mWd( wd )
{
CommsBase( int &rd, int &wd ) : mRd( rd ), mWd( wd ) {
}
virtual ~CommsBase()
{
virtual ~CommsBase() {
}
public:
@ -66,42 +60,35 @@ public:
virtual bool setBlocking( bool blocking )=0;
public:
int getReadDesc() const
{
int getReadDesc() const {
return( mRd );
}
int getWriteDesc() const
{
int getWriteDesc() const {
return( mWd );
}
int getMaxDesc() const
{
int getMaxDesc() const {
return( mRd>mWd?mRd:mWd );
}
virtual int read( void *msg, int len )
{
virtual int read( void *msg, int len ) {
ssize_t nBytes = ::read( mRd, msg, len );
if ( nBytes < 0 )
Debug( 1, "Read of %d bytes max on rd %d failed: %s", len, mRd, strerror(errno) );
return( nBytes );
}
virtual int write( const void *msg, int len )
{
virtual int write( const void *msg, int len ) {
ssize_t nBytes = ::write( mWd, msg, len );
if ( nBytes < 0 )
Debug( 1, "Write of %d bytes on wd %d failed: %s", len, mWd, strerror(errno) );
return( nBytes );
}
virtual int readV( const struct iovec *iov, int iovcnt )
{
virtual int readV( const struct iovec *iov, int iovcnt ) {
int nBytes = ::readv( mRd, iov, iovcnt );
if ( nBytes < 0 )
Debug( 1, "Readv of %d buffers max on rd %d failed: %s", iovcnt, mRd, strerror(errno) );
return( nBytes );
}
virtual int writeV( const struct iovec *iov, int iovcnt )
{
virtual int writeV( const struct iovec *iov, int iovcnt ) {
ssize_t nBytes = ::writev( mWd, iov, iovcnt );
if ( nBytes < 0 )
Debug( 1, "Writev of %d buffers on wd %d failed: %s", iovcnt, mWd, strerror(errno) );
@ -111,19 +98,16 @@ public:
virtual int writeV( int iovcnt, /* const void *msg1, int len1, */ ... );
};
class Pipe : public CommsBase
{
class Pipe : public CommsBase {
protected:
int mFd[2];
public:
Pipe() : CommsBase( mFd[0], mFd[1] )
{
Pipe() : CommsBase( mFd[0], mFd[1] ) {
mFd[0] = -1;
mFd[1] = -1;
}
~Pipe()
{
~Pipe() {
close();
}
@ -147,46 +131,39 @@ public:
bool setBlocking( bool blocking );
};
class SockAddr
{
class SockAddr {
private:
const struct sockaddr *mAddr;
public:
SockAddr( const struct sockaddr *addr );
virtual ~SockAddr()
{
explicit SockAddr( const struct sockaddr *addr );
virtual ~SockAddr() {
}
static SockAddr *newSockAddr( const struct sockaddr &addr, socklen_t len );
static SockAddr *newSockAddr( const SockAddr *addr );
int getDomain() const
{
int getDomain() const {
return( mAddr?mAddr->sa_family:AF_UNSPEC );
}
const struct sockaddr *getAddr() const
{
const struct sockaddr *getAddr() const {
return( mAddr );
}
virtual socklen_t getAddrSize() const=0;
virtual struct sockaddr *getTempAddr() const=0;
};
class SockAddrInet : public SockAddr
{
class SockAddrInet : public SockAddr {
private:
struct sockaddr_in mAddrIn;
struct sockaddr_in mTempAddrIn;
public:
SockAddrInet();
SockAddrInet( const SockAddrInet &addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( addr.mAddrIn )
{
explicit SockAddrInet( const SockAddrInet &addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( addr.mAddrIn ) {
}
SockAddrInet( const struct sockaddr_in *addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( *addr )
{
explicit SockAddrInet( const struct sockaddr_in *addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( *addr ) {
}
@ -195,57 +172,47 @@ public:
bool resolve( const char *serv, const char *proto );
bool resolve( int port, const char *proto );
socklen_t getAddrSize() const
{
socklen_t getAddrSize() const {
return( sizeof(mAddrIn) );
}
struct sockaddr *getTempAddr() const
{
struct sockaddr *getTempAddr() const {
return( (sockaddr *)&mTempAddrIn );
}
public:
static socklen_t addrSize()
{
static socklen_t addrSize() {
return( sizeof(sockaddr_in) );
}
};
class SockAddrUnix : public SockAddr
{
class SockAddrUnix : public SockAddr {
private:
struct sockaddr_un mAddrUn;
struct sockaddr_un mTempAddrUn;
public:
SockAddrUnix();
SockAddrUnix( const SockAddrUnix &addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( addr.mAddrUn )
{
SockAddrUnix( const SockAddrUnix &addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( addr.mAddrUn ) {
}
SockAddrUnix( const struct sockaddr_un *addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( *addr )
{
SockAddrUnix( const struct sockaddr_un *addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( *addr ) {
}
bool resolve( const char *path, const char *proto );
socklen_t getAddrSize() const
{
socklen_t getAddrSize() const {
return( sizeof(mAddrUn) );
}
struct sockaddr *getTempAddr() const
{
struct sockaddr *getTempAddr() const {
return( (sockaddr *)&mTempAddrUn );
}
public:
static socklen_t addrSize()
{
static socklen_t addrSize() {
return( sizeof(sockaddr_un) );
}
};
class Socket : public CommsBase
{
class Socket : public CommsBase {
protected:
typedef enum { CLOSED, DISCONNECTED, LISTENING, CONNECTED } State;
@ -256,45 +223,37 @@ protected:
SockAddr *mRemoteAddr;
protected:
Socket() : CommsBase( mSd, mSd ), mSd( -1 ), mState( CLOSED ), mLocalAddr( 0 ), mRemoteAddr( 0 )
{
Socket() : CommsBase( mSd, mSd ), mSd( -1 ), mState( CLOSED ), mLocalAddr( 0 ), mRemoteAddr( 0 ) {
}
Socket( const Socket &socket, int newSd ) : CommsBase( mSd, mSd ), mSd( newSd ), mState( CONNECTED ), mLocalAddr( 0 ), mRemoteAddr( 0 )
{
Socket( const Socket &socket, int newSd ) : CommsBase( mSd, mSd ), mSd( newSd ), mState( CONNECTED ), mLocalAddr( 0 ), mRemoteAddr( 0 ) {
if ( socket.mLocalAddr )
mLocalAddr = SockAddr::newSockAddr( mLocalAddr );
if ( socket.mRemoteAddr )
mRemoteAddr = SockAddr::newSockAddr( mRemoteAddr );
}
virtual ~Socket()
{
virtual ~Socket() {
close();
delete mLocalAddr;
delete mRemoteAddr;
}
public:
bool isOpen() const
{
bool isOpen() const {
return( !isClosed() );
}
bool isClosed() const
{
bool isClosed() const {
return( mState == CLOSED );
}
bool isDisconnected() const
{
bool isDisconnected() const {
return( mState == DISCONNECTED );
}
bool isConnected() const
{
bool isConnected() const {
return( mState == CONNECTED );
}
virtual bool close();
protected:
bool isListening() const
{
bool isListening() const {
return( mState == LISTENING );
}
@ -309,33 +268,28 @@ protected:
virtual bool accept( int & );
public:
virtual int send( const void *msg, int len ) const
{
virtual int send( const void *msg, int len ) const {
ssize_t nBytes = ::send( mSd, msg, len, 0 );
if ( nBytes < 0 )
Debug( 1, "Send of %d bytes on sd %d failed: %s", len, mSd, strerror(errno) );
return( nBytes );
}
virtual int recv( void *msg, int len ) const
{
virtual int recv( void *msg, int len ) const {
ssize_t nBytes = ::recv( mSd, msg, len, 0 );
if ( nBytes < 0 )
Debug( 1, "Recv of %d bytes max on sd %d failed: %s", len, mSd, strerror(errno) );
return( nBytes );
}
virtual int send( const std::string &msg ) const
{
virtual int send( const std::string &msg ) const {
ssize_t nBytes = ::send( mSd, msg.data(), msg.size(), 0 );
if ( nBytes < 0 )
Debug( 1, "Send of string '%s' (%zd bytes) on sd %d failed: %s", msg.c_str(), msg.size(), mSd, strerror(errno) );
return( nBytes );
}
virtual int recv( std::string &msg ) const
{
virtual int recv( std::string &msg ) const {
char buffer[msg.capacity()];
int nBytes = 0;
if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 )
{
if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 ) {
Debug( 1, "Recv of %zd bytes max to string on sd %d failed: %s", sizeof(buffer), mSd, strerror(errno) );
return( nBytes );
}
@ -343,12 +297,10 @@ public:
msg = buffer;
return( nBytes );
}
virtual int recv( std::string &msg, size_t maxLen ) const
{
virtual int recv( std::string &msg, size_t maxLen ) const {
char buffer[maxLen];
int nBytes = 0;
if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 )
{
if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 ) {
Debug( 1, "Recv of %zd bytes max to string on sd %d failed: %s", maxLen, mSd, strerror(errno) );
return( nBytes );
}
@ -358,8 +310,7 @@ public:
}
virtual int bytesToRead() const;
int getDesc() const
{
int getDesc() const {
return( mSd );
}
//virtual bool isOpen() const
@ -371,12 +322,10 @@ public:
virtual int getType() const=0;
virtual const char *getProtocol() const=0;
const SockAddr *getLocalAddr() const
{
const SockAddr *getLocalAddr() const {
return( mLocalAddr );
}
const SockAddr *getRemoteAddr() const
{
const SockAddr *getRemoteAddr() const {
return( mRemoteAddr );
}
virtual socklen_t getAddrSize() const=0;
@ -403,12 +352,10 @@ protected:
int mAddressFamily;
public:
int getDomain() const
{
int getDomain() const {
return( mAddressFamily );
}
virtual socklen_t getAddrSize() const
{
virtual socklen_t getAddrSize() const {
return( SockAddrInet::addrSize() );
}
@ -422,88 +369,68 @@ protected:
bool bind( int port );
};
class UnixSocket : virtual public Socket
{
class UnixSocket : virtual public Socket {
public:
int getDomain() const
{
int getDomain() const {
return( AF_UNIX );
}
virtual socklen_t getAddrSize() const
{
virtual socklen_t getAddrSize() const {
return( SockAddrUnix::addrSize() );
}
protected:
bool resolveLocal( const char *serv, const char *proto )
{
bool resolveLocal( const char *serv, const char *proto ) {
SockAddrUnix *addr = new SockAddrUnix;
mLocalAddr = addr;
return( addr->resolve( serv, proto ) );
}
bool resolveRemote( const char *path, const char *proto )
{
bool resolveRemote( const char *path, const char *proto ) {
SockAddrUnix *addr = new SockAddrUnix;
mRemoteAddr = addr;
return( addr->resolve( path, proto ) );
}
protected:
bool bind( const char *path )
{
bool bind( const char *path ) {
if ( !UnixSocket::resolveLocal( path, getProtocol() ) )
return( false );
return( Socket::bind() );
}
bool connect( const char *path )
{
bool connect( const char *path ) {
if ( !UnixSocket::resolveRemote( path, getProtocol() ) )
return( false );
return( Socket::connect() );
}
};
class UdpSocket : virtual public Socket
{
class UdpSocket : virtual public Socket {
public:
int getType() const
{
int getType() const {
return( SOCK_DGRAM );
}
const char *getProtocol() const
{
const char *getProtocol() const {
return( "udp" );
}
public:
virtual int sendto( const void *msg, int len, const SockAddr *addr=0 ) const
{
virtual int sendto( const void *msg, int len, const SockAddr *addr=0 ) const {
ssize_t nBytes = ::sendto( mSd, msg, len, 0, addr?addr->getAddr():NULL, addr?addr->getAddrSize():0 );
if ( nBytes < 0 )
Debug( 1, "Sendto of %d bytes on sd %d failed: %s", len, mSd, strerror(errno) );
return( nBytes );
}
virtual int recvfrom( void *msg, int len, SockAddr *addr=0 ) const
{
virtual int recvfrom( void *msg, int len, SockAddr *addr=0 ) const {
ssize_t nBytes = 0;
if ( addr )
{
if ( addr ) {
struct sockaddr sockAddr;
socklen_t sockLen;
nBytes = ::recvfrom( mSd, msg, len, 0, &sockAddr, &sockLen );
if ( nBytes < 0 )
{
if ( nBytes < 0 ) {
Debug( 1, "Recvfrom of %d bytes max on sd %d (with address) failed: %s", len, mSd, strerror(errno) );
}
else if ( sockLen )
{
addr = SockAddr::newSockAddr( sockAddr, sockLen );
}
}
else
{
} else {
nBytes = ::recvfrom( mSd, msg, len, 0, NULL, 0 );
if ( nBytes < 0 )
Debug( 1, "Recvfrom of %d bytes max on sd %d (no address) failed: %s", len, mSd, strerror(errno) );
@ -512,194 +439,150 @@ public:
}
};
class UdpInetSocket : virtual public UdpSocket, virtual public InetSocket
{
class UdpInetSocket : virtual public UdpSocket, virtual public InetSocket {
public:
bool bind( const char *host, const char *serv )
{
bool bind( const char *host, const char *serv ) {
return( InetSocket::bind( host, serv ) );
}
bool bind( const char *host, int port )
{
bool bind( const char *host, int port ) {
return( InetSocket::bind( host, port ) );
}
bool bind( const char *serv )
{
bool bind( const char *serv ) {
return( InetSocket::bind( serv ) );
}
bool bind( int port )
{
bool bind( int port ) {
return( InetSocket::bind( port ) );
}
bool connect( const char *host, const char *serv )
{
bool connect( const char *host, const char *serv ) {
return( InetSocket::connect( host, serv ) );
}
bool connect( const char *host, int port )
{
bool connect( const char *host, int port ) {
return( InetSocket::connect( host, port ) );
}
};
class UdpUnixSocket : virtual public UdpSocket, virtual public UnixSocket
{
class UdpUnixSocket : virtual public UdpSocket, virtual public UnixSocket {
public:
bool bind( const char *path )
{
bool bind( const char *path ) {
return( UnixSocket::bind( path ) );
}
bool connect( const char *path )
{
bool connect( const char *path ) {
return( UnixSocket::connect( path ) );
}
};
class UdpInetClient : public UdpInetSocket
{
class UdpInetClient : public UdpInetSocket {
public:
bool connect( const char *host, const char *serv )
{
bool connect( const char *host, const char *serv ) {
return( UdpInetSocket::connect( host, serv ) );
}
bool connect( const char *host, int port )
{
bool connect( const char *host, int port ) {
return( UdpInetSocket::connect( host, port ) );
}
};
class UdpUnixClient : public UdpUnixSocket
{
class UdpUnixClient : public UdpUnixSocket {
public:
bool bind( const char *path )
{
bool bind( const char *path ) {
return( UdpUnixSocket::bind( path ) );
}
public:
bool connect( const char *path )
{
bool connect( const char *path ) {
return( UdpUnixSocket::connect( path) );
}
};
class UdpInetServer : public UdpInetSocket
{
class UdpInetServer : public UdpInetSocket {
public:
bool bind( const char *host, const char *serv )
{
bool bind( const char *host, const char *serv ) {
return( UdpInetSocket::bind( host, serv ) );
}
bool bind( const char *host, int port )
{
bool bind( const char *host, int port ) {
return( UdpInetSocket::bind( host, port ) );
}
bool bind( const char *serv )
{
bool bind( const char *serv ) {
return( UdpInetSocket::bind( serv ) );
}
bool bind( int port )
{
bool bind( int port ) {
return( UdpInetSocket::bind( port ) );
}
protected:
bool connect( const char *host, const char *serv )
{
bool connect( const char *host, const char *serv ) {
return( UdpInetSocket::connect( host, serv ) );
}
bool connect( const char *host, int port )
{
bool connect( const char *host, int port ) {
return( UdpInetSocket::connect( host, port ) );
}
};
class UdpUnixServer : public UdpUnixSocket
{
class UdpUnixServer : public UdpUnixSocket {
public:
bool bind( const char *path )
{
bool bind( const char *path ) {
return( UdpUnixSocket::bind( path ) );
}
protected:
bool connect( const char *path )
{
bool connect( const char *path ) {
return( UdpUnixSocket::connect( path ) );
}
};
class TcpSocket : virtual public Socket
{
class TcpSocket : virtual public Socket {
public:
TcpSocket()
{
TcpSocket() {
}
TcpSocket( const TcpSocket &socket, int newSd ) : Socket( socket, newSd )
{
TcpSocket( const TcpSocket &socket, int newSd ) : Socket( socket, newSd ) {
}
public:
int getType() const
{
int getType() const {
return( SOCK_STREAM );
}
const char *getProtocol() const
{
const char *getProtocol() const {
return( "tcp" );
}
};
class TcpInetSocket : virtual public TcpSocket, virtual public InetSocket
{
class TcpInetSocket : virtual public TcpSocket, virtual public InetSocket {
public:
TcpInetSocket()
{
TcpInetSocket() {
}
TcpInetSocket( const TcpInetSocket &socket, int newSd ) : TcpSocket( socket, newSd )
{
TcpInetSocket( const TcpInetSocket &socket, int newSd ) : TcpSocket( socket, newSd ) {
}
};
class TcpUnixSocket : virtual public TcpSocket, virtual public UnixSocket
{
class TcpUnixSocket : virtual public TcpSocket, virtual public UnixSocket {
public:
TcpUnixSocket()
{
TcpUnixSocket() {
}
TcpUnixSocket( const TcpUnixSocket &socket, int newSd ) : TcpSocket( socket, newSd )
{
TcpUnixSocket( const TcpUnixSocket &socket, int newSd ) : TcpSocket( socket, newSd ) {
}
};
class TcpInetClient : public TcpInetSocket
{
class TcpInetClient : public TcpInetSocket {
public:
bool connect( const char *host, const char *serv )
{
bool connect( const char *host, const char *serv ) {
return( TcpInetSocket::connect( host, serv ) );
}
bool connect( const char *host, int port )
{
bool connect( const char *host, int port ) {
return( TcpInetSocket::connect( host, port ) );
}
};
class TcpUnixClient : public TcpUnixSocket
{
class TcpUnixClient : public TcpUnixSocket {
public:
bool connect( const char *path )
{
bool connect( const char *path ) {
return( TcpUnixSocket::connect( path) );
}
};
class TcpInetServer : public TcpInetSocket
{
class TcpInetServer : public TcpInetSocket {
public:
bool bind( int port )
{
bool bind( int port ) {
return( TcpInetSocket::bind( port ) );
}
@ -710,11 +593,9 @@ public:
bool accept( TcpInetSocket *&newSocket );
};
class TcpUnixServer : public TcpUnixSocket
{
class TcpUnixServer : public TcpUnixSocket {
public:
bool bind( const char *path )
{
bool bind( const char *path ) {
return( TcpUnixSocket::bind( path ) );
}
@ -725,8 +606,7 @@ public:
bool accept( TcpUnixSocket *&newSocket );
};
class Select
{
class Select {
public:
typedef std::set<CommsBase *> CommsSet;
typedef std::vector<CommsBase *> CommsList;

View File

@ -216,6 +216,33 @@ ConfigItem::ConfigItem( const char *p_name, const char *p_value, const char *con
accessed = false;
}
ConfigItem::ConfigItem( const ConfigItem &item ) {
name = new char[strlen(item.name)+1];
strcpy( name, item.name );
value = new char[strlen(item.value)+1];
strcpy( value, item.value );
type = new char[strlen(item.type)+1];
strcpy( type, item.type );
//Info( "Created new config item %s = %s (%s)\n", name, value, type );
accessed = false;
}
void ConfigItem::Copy( const ConfigItem &item ) {
if (name) delete name;
name = new char[strlen(item.name)+1];
strcpy( name, item.name );
if (value) delete value;
value = new char[strlen(item.value)+1];
strcpy( value, item.value );
if (type) delete type;
type = new char[strlen(item.type)+1];
strcpy( type, item.type );
//Info( "Created new config item %s = %s (%s)\n", name, value, type );
accessed = false;
}
ConfigItem::~ConfigItem() {
delete[] name;
delete[] value;

View File

@ -107,25 +107,30 @@ private:
mutable bool accessed;
public:
ConfigItem( const char *p_name, const char *p_value, const char *const p_type );
ConfigItem(const char *p_name, const char *p_value, const char *const p_type);
ConfigItem(const ConfigItem &);
~ConfigItem();
void Copy(const ConfigItem&);
void ConvertValue() const;
bool BooleanValue() const;
int IntegerValue() const;
double DecimalValue() const;
const char *StringValue() const;
ConfigItem &operator=(const ConfigItem item) {
Copy(item);return *this;
}
inline operator bool() const {
return( BooleanValue() );
return BooleanValue();
}
inline operator int() const {
return( IntegerValue() );
return IntegerValue();
}
inline operator double() const {
return( DecimalValue() );
return DecimalValue();
}
inline operator const char *() const {
return( StringValue() );
return StringValue();
}
};

View File

@ -31,14 +31,13 @@ private:
int x, y;
public:
inline Coord() : x(0), y(0)
{
}
inline Coord( int p_x, int p_y ) : x(p_x), y(p_y)
{
}
inline Coord( const Coord &p_coord ) : x(p_coord.x), y(p_coord.y)
{
inline Coord() : x(0), y(0) { }
inline Coord( int p_x, int p_y ) : x(p_x), y(p_y) { }
inline Coord( const Coord &p_coord ) : x(p_coord.x), y(p_coord.y) { }
inline Coord &operator =( const Coord &coord ) {
x = coord.x;
y = coord.y;
return *this;
}
inline int &X() { return( x ); }
inline const int &X() const { return( x ); }

View File

@ -236,10 +236,10 @@ int cURLCamera::Capture( Image &image ) {
if(!SubHeadersParsingComplete) {
/* We haven't parsed all headers yet */
need_more_data = true;
} else if(frame_content_length <= 0) {
} else if ( ! frame_content_length ) {
/* Invalid frame */
Error("Invalid frame: invalid content length");
} else if(frame_content_type != "image/jpeg") {
} else if ( frame_content_type != "image/jpeg" ) {
/* Unsupported frame type */
Error("Unsupported frame: %s",frame_content_type.c_str());
} else if(frame_content_length > databuffer.size()) {
@ -526,19 +526,19 @@ int cURLCamera::progress_callback(void *userdata, double dltotal, double dlnow,
/* These functions call the functions in the class for the correct object */
size_t data_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata) {
return ((cURLCamera*)userdata)->data_callback(buffer,size,nmemb,userdata);
return reinterpret_cast<cURLCamera*>(userdata)->data_callback(buffer,size,nmemb,userdata);
}
size_t header_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata) {
return ((cURLCamera*)userdata)->header_callback(buffer,size,nmemb,userdata);
return reinterpret_cast<cURLCamera*>(userdata)->header_callback(buffer,size,nmemb,userdata);
}
int progress_callback_dispatcher(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow) {
return ((cURLCamera*)userdata)->progress_callback(userdata,dltotal,dlnow,ultotal,ulnow);
return reinterpret_cast<cURLCamera*>(userdata)->progress_callback(userdata,dltotal,dlnow,ultotal,ulnow);
}
void* thread_func_dispatcher(void* object) {
return ((cURLCamera*)object)->thread_func();
return reinterpret_cast<cURLCamera*>(object)->thread_func();
}
#endif // HAVE_LIBCURL

View File

@ -71,7 +71,7 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
static char sql[ZM_SQL_MED_BUFSIZ];
struct tm *stime = localtime( &start_time.tv_sec );
snprintf( sql, sizeof(sql), "insert into Events ( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed ) values ( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d, %d, %d )",
snprintf( sql, sizeof(sql), "INSERT INTO Events ( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed, DefaultVideo, SaveJPEGs ) values ( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d, %d, %d, '', %d )",
monitor->Id(),
storage->Id(),
start_time.tv_sec,
@ -81,7 +81,8 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
notes.c_str(),
state_id,
monitor->getOrientation(),
videoEvent
videoEvent,
monitor->GetOptSaveJPEGs()
);
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert event: %s. sql was (%s)", mysql_error( &dbconn ), sql );
@ -211,7 +212,9 @@ Event::~Event() {
if ( frames > last_db_frame ) {
Debug( 1, "Adding closing frame %d to DB", frames );
snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )", id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
snprintf( sql, sizeof(sql),
"insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )",
id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert frame: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
@ -241,11 +244,11 @@ Event::~Event() {
void Event::createNotes( std::string &notes ) {
notes.clear();
for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); mapIter++ ) {
for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); ++mapIter ) {
notes += mapIter->first;
notes += ": ";
const StringSet &stringSet = mapIter->second;
for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); setIter++ ) {
for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); ++setIter ) {
if ( setIter != stringSet.begin() )
notes += ", ";
notes += *setIter;
@ -316,7 +319,7 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
noteSetMap = newNoteSetMap;
update = true;
} else {
for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); newNoteSetMapIter++ ) {
for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); ++newNoteSetMapIter ) {
const std::string &newNoteGroup = newNoteSetMapIter->first;
const StringSet &newNoteSet = newNoteSetMapIter->second;
//Info( "Got %d new strings", newNoteSet.size() );
@ -329,7 +332,7 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
} else {
StringSet &noteSet = noteSetMapIter->second;
//Info( "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size() );
for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); newNoteSetIter++ ) {
for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); ++newNoteSetIter ) {
const std::string &newNote = *newNoteSetIter;
StringSet::iterator noteSetIter = noteSet.find( newNote );
if ( noteSetIter == noteSet.end() ) {
@ -390,7 +393,6 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
}
strncpy( notesStr, notes.c_str(), sizeof(notesStr) );
notesLen = notes.length();
if ( mysql_stmt_execute( stmt ) ) {
Fatal( "Unable to execute sql '%s': %s", sql, mysql_stmt_error(stmt) );

View File

@ -176,13 +176,13 @@ bool EventStream::loadEventData( int event_id ) {
event_data->n_frames = mysql_num_rows( result );
event_data->frames = new FrameData[event_data->frame_count];
int id, last_id = 0;
int last_id = 0;
time_t timestamp, last_timestamp = event_data->start_time;
double delta, last_delta = 0.0;
double last_delta = 0.0;
while ( ( dbrow = mysql_fetch_row( result ) ) ) {
id = atoi(dbrow[0]);
int id = atoi(dbrow[0]);
timestamp = atoi(dbrow[1]);
delta = atof(dbrow[2]);
double delta = atof(dbrow[2]);
int id_diff = id - last_id;
double frame_delta = (delta-last_delta)/id_diff;
if ( id_diff > 1 ) {
@ -414,7 +414,6 @@ void EventStream::processCommand( const CmdMsg *msg ) {
}
send_frame = true;
break;
send_frame = true;
}
case CMD_PAN :
{
@ -593,6 +592,7 @@ bool EventStream::sendFrame( int delta_us ) {
FILE *fdj = NULL;
// This needs to be abstracted. If we are saving jpgs, then load the capture file. If we are only saving analysis frames, then send that.
// // This is also wrong, need to have this info stored in the event! FIXME
if ( monitor->GetOptSaveJPEGs() & 1 ) {
snprintf( filepath, sizeof(filepath), staticConfig.capture_file_format, event_data->path, curr_frame_id );
} else if ( monitor->GetOptSaveJPEGs() & 2 ) {

View File

@ -27,6 +27,7 @@
#include "zm_stream.h"
#include "zm_video.h"
#include "zm_ffmpeg_input.h"
#include "zm_monitor.h"
#ifdef __cplusplus
extern "C" {
@ -74,7 +75,7 @@ class EventStream : public StreamBase {
int curr_frame_id;
double curr_stream_time;
bool send_frame;
bool send_frame;
EventData *event_data;
FFmpeg_Input *ffmpeg_input;
@ -96,6 +97,7 @@ class EventStream : public StreamBase {
curr_frame_id = 0;
curr_stream_time = 0.0;
send_frame = false;
event_data = 0;
@ -108,11 +110,17 @@ class EventStream : public StreamBase {
}
void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) {
loadInitialEventData( init_event_id, init_frame_id );
loadMonitor( event_data->monitor_id );
if ( !(monitor = Monitor::Load( event_data->monitor_id, false, Monitor::QUERY )) ) {
Fatal( "Unable to load monitor id %d for streaming", event_data->monitor_id );
return;
}
}
void setStreamStart( int monitor_id, time_t event_time ) {
loadInitialEventData( monitor_id, event_time );
loadMonitor( monitor_id );
if ( !(monitor = Monitor::Load( event_data->monitor_id, false, Monitor::QUERY )) ) {
Fatal( "Unable to load monitor id %d for streaming", monitor_id );
return;
}
}
void setStreamMode( StreamMode p_mode ) {
mode = p_mode;

View File

@ -109,8 +109,6 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
const char *key_val_sep, const char *pairs_sep,
int flags)
{
int ret;
if (!str)
return 0;
@ -118,7 +116,7 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
flags &= ~(AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
while (*str) {
if ((ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
if ((int ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
return ret;
if (*str)
@ -133,6 +131,7 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
#endif // HAVE_LIBAVCODEC || HAVE_LIBAVUTIL || HAVE_LIBSWSCALE
#if HAVE_LIBAVUTIL
#if LIBAVUTIL_VERSION_CHECK(56, 0, 0, 17, 100)
int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb){
int64_t a, b, this_thing;
@ -156,6 +155,7 @@ simple_round:
return av_rescale_q(this_thing, fs_tb, out_tb);
}
#endif
#endif
int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat *oformat, const char *format, const char *filename) {
AVFormatContext *s = avformat_alloc_context();
@ -184,27 +184,13 @@ int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat
}
}
if (!oformat) {
if (format) {
oformat = av_guess_format(format, NULL, NULL);
if (!oformat) {
av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format);
ret = AVERROR(EINVAL);
}
} else {
oformat = av_guess_format(NULL, filename, NULL);
if (!oformat) {
ret = AVERROR(EINVAL);
av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n", filename);
}
}
}
if (ret) {
avformat_free_context(s);
return ret;
} else {
s->oformat = oformat;
#if 0
// This is some very wrong code, and I don't think it is neccessary
if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (s->priv_data) {
@ -219,6 +205,7 @@ int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat
}
s->priv_data = NULL;
}
#endif
if (filename) strncpy(s->filename, filename, sizeof(s->filename));
*avctx = s;

View File

@ -205,7 +205,6 @@ int FfmpegCamera::Capture( Image &image ) {
int frameComplete = false;
while ( !frameComplete ) {
int ret;
int avResult = av_read_frame( mFormatContext, &packet );
char errbuf[AV_ERROR_MAX_STRING_SIZE];
if ( avResult < 0 ) {
@ -231,6 +230,7 @@ int FfmpegCamera::Capture( Image &image ) {
Debug( 5, "Got packet from stream %d dts (%d) pts(%d)", packet.stream_index, packet.pts, packet.dts );
// What about audio stream? Maybe someday we could do sound detection...
if ( ( packet.stream_index == mVideoStreamId ) && ( keyframe || have_video_keyframe ) ) {
int ret;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
ret = avcodec_send_packet( mVideoCodecContext, &packet );
if ( ret < 0 ) {
@ -458,7 +458,9 @@ int FfmpegCamera::OpenFfmpeg() {
// STolen from ispy
//this fixes issues with rtsp streams!! woot.
//mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG2_CHUNKS | CODEC_FLAG_LOW_DELAY; // Enable faster H264 decode.
#ifdef CODEC_FLAG2_FAST
mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG_LOW_DELAY;
#endif
#if HAVE_AVUTIL_HWCONTEXT_H
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H264 ) {
@ -836,7 +838,6 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
videoStore = NULL;
} else {
strcpy(oldDirectory, event_file);
monitor->SetVideoWriterEventId( last_event_id );
// Need to write out all the frames from the last keyframe?

View File

@ -85,8 +85,6 @@ class FfmpegCamera : public Camera {
#endif // HAVE_LIBAVFORMAT
VideoStore *videoStore;
char oldDirectory[4096];
unsigned int old_event_id;
zm_packetqueue packetqueue;
bool have_video_keyframe;

View File

@ -9,9 +9,14 @@ FFmpeg_Input::FFmpeg_Input() {
audio_stream_id = -1;
av_register_all();
avcodec_register_all();
streams = NULL;
}
FFmpeg_Input::~FFmpeg_Input() {
if ( streams ) {
delete streams;
streams = NULL;
}
}
int FFmpeg_Input::Open( const char *filepath ) {
@ -35,6 +40,8 @@ int FFmpeg_Input::Open( const char *filepath ) {
return error;
}
streams = new stream[input_format_context->nb_streams];
for ( unsigned int i = 0; i < input_format_context->nb_streams; i += 1 ) {
if ( is_video_stream( input_format_context->streams[i] ) ) {
zm_dump_stream_format(input_format_context, i, 0, 0);
@ -162,7 +169,7 @@ AVFrame *FFmpeg_Input::get_frame( int stream_id ) {
frameComplete = 1;
# else
ret = zm_avcodec_decode_video( streams[packet.stream_index].context, frame, &frameComplete, &packet );
ret = zm_avcodec_decode_video( context, frame, &frameComplete, &packet );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to decode frame at frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );

View File

@ -36,7 +36,7 @@ class FFmpeg_Input {
int frame_count;
} stream;
stream streams[2];
stream *streams;
int video_stream_id;
int audio_stream_id;
AVFormatContext *input_format_context;

View File

@ -131,6 +131,7 @@ Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uin
Image::Image( const AVFrame *frame ) {
AVFrame *dest_frame = zm_av_frame_alloc();
text[0] = '\0';
width = frame->width;
height = frame->height;
@ -457,7 +458,6 @@ void Image::Initialise() {
/* Requests a writeable buffer to the image. This is safer than buffer() because this way we can guarantee that a buffer of required size exists */
uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder) {
unsigned int newsize;
if ( p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32 ) {
Error("WriteBuffer called with unexpected colours: %d",p_colours);
@ -470,7 +470,7 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
}
if ( p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder ) {
newsize = (p_width * p_height) * p_colours;
unsigned int newsize = (p_width * p_height) * p_colours;
if ( buffer == NULL ) {
AllocImgBuffer(newsize);
@ -613,12 +613,12 @@ void Image::Assign(const unsigned int p_width, const unsigned int p_height, cons
void Image::Assign( const Image &image ) {
unsigned int new_size = (image.width * image.height) * image.colours;
if(image.buffer == NULL) {
if ( image.buffer == NULL ) {
Error("Attempt to assign image with an empty buffer");
return;
}
if(image.colours != ZM_COLOUR_GRAY8 && image.colours != ZM_COLOUR_RGB24 && image.colours != ZM_COLOUR_RGB32) {
if ( image.colours != ZM_COLOUR_GRAY8 && image.colours != ZM_COLOUR_RGB24 && image.colours != ZM_COLOUR_RGB32 ) {
Error("Attempt to assign image with unexpected colours per pixel: %d",image.colours);
return;
}
@ -1848,8 +1848,7 @@ void Image::Delta( const Image &image, Image* targetimage) const
#endif
}
const Coord Image::centreCoord( const char *text ) const
{
const Coord Image::centreCoord( const char *text ) const {
int index = 0;
int line_no = 0;
int text_len = strlen( text );
@ -1857,14 +1856,12 @@ const Coord Image::centreCoord( const char *text ) const
int max_line_len = 0;
const char *line = text;
while ( (index < text_len) && (line_len = strcspn( line, "\n" )) )
{
while ( (index < text_len) && (line_len = strcspn( line, "\n" )) ) {
if ( line_len > max_line_len )
max_line_len = line_len;
index += line_len;
while ( text[index] == '\n' )
{
while ( text[index] == '\n' ) {
index++;
}
line = text+index;
@ -1876,8 +1873,7 @@ const Coord Image::centreCoord( const char *text ) const
}
/* RGB32 compatible: complete */
void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour )
{
void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour ) {
const uint8_t pixel_r_col = RED_VAL_RGBA(pixel_colour);
const uint8_t pixel_g_col = GREEN_VAL_RGBA(pixel_colour);
const uint8_t pixel_b_col = BLUE_VAL_RGBA(pixel_colour);
@ -2102,8 +2098,8 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
void Image::Timestamp( const char *label, const time_t when, const Coord &coord, const int size ) {
char time_text[64];
strftime( time_text, sizeof(time_text), "%y/%m/%d %H:%M:%S", localtime( &when ) );
char text[64];
if ( label ) {
char text[64];
snprintf( text, sizeof(text), "%s - %s", label, time_text );
Annotate( text, coord, size );
} else {
@ -2625,8 +2621,7 @@ void Image::Rotate( int angle )
unsigned int new_width = width;
uint8_t* rotate_buffer = AllocBuffer(size);
switch( angle )
{
switch( angle ) {
case 90 :
{
new_height = width;
@ -2635,41 +2630,27 @@ void Image::Rotate( int angle )
unsigned int line_bytes = new_width*colours;
unsigned char *s_ptr = buffer;
if ( colours == ZM_COLOUR_GRAY8 )
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- )
{
if ( colours == ZM_COLOUR_GRAY8 ) {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- ) {
*d_ptr = *s_ptr++;
d_ptr += line_bytes;
}
}
}
else if ( colours == ZM_COLOUR_RGB32 )
{
} else if ( colours == ZM_COLOUR_RGB32 ) {
Rgb* s_rptr = (Rgb*)s_ptr;
Rgb* d_rptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- )
{
for ( unsigned int i = new_width; i > 0; i-- ) {
Rgb* d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- ) {
*d_rptr = *s_rptr++;
d_rptr += new_width;
}
}
}
else /* Assume RGB24 */
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- )
{
} else /* Assume RGB24 */ {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- ) {
*d_ptr = *s_ptr++;
*(d_ptr+1) = *s_ptr++;
*(d_ptr+2) = *s_ptr++;
@ -2684,28 +2665,20 @@ void Image::Rotate( int angle )
unsigned char *s_ptr = buffer+size;
unsigned char *d_ptr = rotate_buffer;
if ( colours == ZM_COLOUR_GRAY8 )
{
while( s_ptr > buffer )
{
if ( colours == ZM_COLOUR_GRAY8 ) {
while( s_ptr > buffer ) {
s_ptr--;
*d_ptr++ = *s_ptr;
}
}
else if ( colours == ZM_COLOUR_RGB32 )
{
} else if ( colours == ZM_COLOUR_RGB32 ) {
Rgb* s_rptr = (Rgb*)s_ptr;
Rgb* d_rptr = (Rgb*)d_ptr;
while( s_rptr > (Rgb*)buffer )
{
while( s_rptr > (Rgb*)buffer ) {
s_rptr--;
*d_rptr++ = *s_rptr;
}
}
else /* Assume RGB24 */
{
while( s_ptr > buffer )
{
} else /* Assume RGB24 */ {
while( s_ptr > buffer ) {
s_ptr -= 3;
*d_ptr++ = *s_ptr;
*d_ptr++ = *(s_ptr+1);
@ -2722,43 +2695,29 @@ void Image::Rotate( int angle )
unsigned int line_bytes = new_width*colours;
unsigned char *s_ptr = buffer+size;
if ( colours == ZM_COLOUR_GRAY8 )
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- )
{
if ( colours == ZM_COLOUR_GRAY8 ) {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- ) {
s_ptr--;
*d_ptr = *s_ptr;
d_ptr += line_bytes;
}
}
}
else if ( colours == ZM_COLOUR_RGB32 )
{
} else if ( colours == ZM_COLOUR_RGB32 ) {
Rgb* s_rptr = (Rgb*)s_ptr;
Rgb* d_rptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- )
{
for ( unsigned int i = new_width; i > 0; i-- ) {
Rgb* d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- ) {
s_rptr--;
*d_rptr = *s_rptr;
d_rptr += new_width;
}
}
}
else /* Assume RGB24 */
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- )
{
} else /* Assume RGB24 */ {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- ) {
*(d_ptr+2) = *(--s_ptr);
*(d_ptr+1) = *(--s_ptr);
*d_ptr = *(--s_ptr);
@ -2771,18 +2730,15 @@ void Image::Rotate( int angle )
}
AssignDirect( new_width, new_height, colours, subpixelorder, rotate_buffer, size, ZM_BUFTYPE_ZM);
}
/* RGB32 compatible: complete */
void Image::Flip( bool leftright )
{
void Image::Flip( bool leftright ) {
uint8_t* flip_buffer = AllocBuffer(size);
unsigned int line_bytes = width*colours;
unsigned int line_bytes2 = 2*line_bytes;
if ( leftright )
{
if ( leftright ) {
// Horizontal flip, left to right
unsigned char *s_ptr = buffer+line_bytes;
unsigned char *d_ptr = flip_buffer;

View File

@ -95,14 +95,14 @@ protected:
double _1_m;
static int CompareYX( const void *p1, const void *p2 ) {
const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2;
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
if ( e1->min_y == e2->min_y )
return( int(e1->min_x - e2->min_x) );
else
return( int(e1->min_y - e2->min_y) );
}
static int CompareX( const void *p1, const void *p2 ) {
const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2;
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
return( int(e1->min_x - e2->min_x) );
}
};
@ -152,10 +152,10 @@ protected:
public:
Image();
Image( const char *filename );
explicit Image( const char *filename );
Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0);
Image( const Image &p_image );
Image( const AVFrame *frame );
explicit Image( const Image &p_image );
explicit Image( const AVFrame *frame );
~Image();
static void Initialise();
static void Deinitialise();

View File

@ -276,8 +276,7 @@ static boolean fill_input_buffer (j_decompress_ptr cinfo)
memcpy( src->buffer, src->inbuffer, (size_t) src->inbuffer_size );
nbytes = src->inbuffer_size;
if ( nbytes <= 0 )
{
if ( nbytes == 0 ) {
if ( src->start_of_data ) /* Treat empty input file as fatal error */
ERREXIT(cinfo, JERR_INPUT_EMPTY);
WARNMS(cinfo, JWRN_JPEG_EOF);

View File

@ -24,7 +24,7 @@
// Do all the buffer checking work here to avoid unnecessary locking
void* LibvlcLockBuffer(void* opaque, void** planes) {
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
LibvlcPrivateData* data = reinterpret_cast<LibvlcPrivateData*>(opaque);
data->mutex.lock();
uint8_t* buffer = data->buffer;
@ -36,7 +36,7 @@ void* LibvlcLockBuffer(void* opaque, void** planes) {
}
void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes) {
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
LibvlcPrivateData* data = reinterpret_cast<LibvlcPrivateData*>(opaque);
bool newFrame = false;
for( uint32_t i = 0; i < data->bufferSize; i++ ) {
@ -67,6 +67,7 @@ LibvlcCamera::LibvlcCamera( int p_id, const std::string &p_path, const std::stri
mLibvlcMediaPlayer = NULL;
mLibvlcData.buffer = NULL;
mLibvlcData.prevBuffer = NULL;
mOptArgV = NULL;
/* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */
if(colours == ZM_COLOUR_RGB32) {

View File

@ -1534,34 +1534,28 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
return( false );
}
if ( verbose )
{
if ( verbose ) {
sprintf( output+strlen(output), " Input %d\n", input.index );
sprintf( output+strlen(output), " Name: %s\n", input.name );
sprintf( output+strlen(output), " Type: %s\n", input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
sprintf( output+strlen(output), " Audioset: %08x\n", input.audioset );
sprintf( output+strlen(output), " Standards: 0x%llx\n", input.std );
}
else
{
} else {
sprintf( output+strlen(output), "i%d:%s|", input.index, input.name );
sprintf( output+strlen(output), "i%dT:%s|", input.index, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
sprintf( output+strlen(output), "i%dS:%llx|", input.index, input.std );
}
if ( verbose )
{
if ( verbose ) {
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_POWER, "Power ", "off", "on", " (X)" ) );
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_SIGNAL, "Signal ", "not detected", "detected", " (X)" ) );
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_COLOR, "Colour Signal ", "not detected", "detected", "" ) );
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_H_LOCK, "Horizontal Lock ", "not detected", "detected", "" ) );
}
else
{
sprintf( output+strlen(output), "i%dSP:%d|", input.index, input.status&V4L2_IN_ST_NO_POWER?0:1 );
sprintf( output+strlen(output), "i%dSS:%d|", input.index, input.status&V4L2_IN_ST_NO_SIGNAL?0:1 );
sprintf( output+strlen(output), "i%dSC:%d|", input.index, input.status&V4L2_IN_ST_NO_COLOR?0:1 );
sprintf( output+strlen(output), "i%dHP:%d|", input.index, input.status&V4L2_IN_ST_NO_H_LOCK?0:1 );
} else {
sprintf( output+strlen(output), "i%dSP:%d|", input.index, (input.status&V4L2_IN_ST_NO_POWER)?0:1 );
sprintf( output+strlen(output), "i%dSS:%d|", input.index, (input.status&V4L2_IN_ST_NO_SIGNAL)?0:1 );
sprintf( output+strlen(output), "i%dSC:%d|", input.index, (input.status&V4L2_IN_ST_NO_COLOR)?0:1 );
sprintf( output+strlen(output), "i%dHP:%d|", input.index, (input.status&V4L2_IN_ST_NO_H_LOCK)?0:1 );
}
}
while ( inputIndex++ >= 0 );
@ -1570,12 +1564,10 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
}
#endif // ZM_HAS_V4L2
#if ZM_HAS_V4L1
if ( version == 1 )
{
if ( version == 1 ) {
struct video_capability vid_cap;
memset( &vid_cap, 0, sizeof(video_capability) );
if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 )
{
if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 ) {
Error( "Failed to get video capabilities: %s", strerror(errno) );
if ( verbose )
sprintf( output, "Error, failed to get video capabilities %s: %s\n", queryDevice, strerror(errno) );
@ -1583,25 +1575,24 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
sprintf( output, "error%d\n", errno );
return( false );
}
if ( verbose )
{
if ( verbose ) {
sprintf( output+strlen(output), "Video Capabilities\n" );
sprintf( output+strlen(output), " Name: %s\n", vid_cap.name );
sprintf( output+strlen(output), " Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.type,
vid_cap.type&VID_TYPE_CAPTURE?" Can capture\n":"",
vid_cap.type&VID_TYPE_TUNER?" Can tune\n":"",
vid_cap.type&VID_TYPE_TELETEXT?" Does teletext\n":"",
vid_cap.type&VID_TYPE_OVERLAY?" Overlay onto frame buffer\n":"",
vid_cap.type&VID_TYPE_CHROMAKEY?" Overlay by chromakey\n":"",
vid_cap.type&VID_TYPE_CLIPPING?" Can clip\n":"",
vid_cap.type&VID_TYPE_FRAMERAM?" Uses the frame buffer memory\n":"",
vid_cap.type&VID_TYPE_SCALES?" Scalable\n":"",
vid_cap.type&VID_TYPE_MONOCHROME?" Monochrome only\n":"",
vid_cap.type&VID_TYPE_SUBCAPTURE?" Can capture subareas of the image\n":"",
vid_cap.type&VID_TYPE_MPEG_DECODER?" Can decode MPEG streams\n":"",
vid_cap.type&VID_TYPE_MPEG_ENCODER?" Can encode MPEG streams\n":"",
vid_cap.type&VID_TYPE_MJPEG_DECODER?" Can decode MJPEG streams\n":"",
vid_cap.type&VID_TYPE_MJPEG_ENCODER?" Can encode MJPEG streams\n":""
(vid_cap.type&VID_TYPE_CAPTURE)?" Can capture\n":"",
(vid_cap.type&VID_TYPE_TUNER)?" Can tune\n":"",
(vid_cap.type&VID_TYPE_TELETEXT)?" Does teletext\n":"",
(vid_cap.type&VID_TYPE_OVERLAY)?" Overlay onto frame buffer\n":"",
(vid_cap.type&VID_TYPE_CHROMAKEY)?" Overlay by chromakey\n":"",
(vid_cap.type&VID_TYPE_CLIPPING)?" Can clip\n":"",
(vid_cap.type&VID_TYPE_FRAMERAM)?" Uses the frame buffer memory\n":"",
(vid_cap.type&VID_TYPE_SCALES)?" Scalable\n":"",
(vid_cap.type&VID_TYPE_MONOCHROME)?" Monochrome only\n":"",
(vid_cap.type&VID_TYPE_SUBCAPTURE)?" Can capture subareas of the image\n":"",
(vid_cap.type&VID_TYPE_MPEG_DECODER)?" Can decode MPEG streams\n":"",
(vid_cap.type&VID_TYPE_MPEG_ENCODER)?" Can encode MPEG streams\n":"",
(vid_cap.type&VID_TYPE_MJPEG_DECODER)?" Can decode MJPEG streams\n":"",
(vid_cap.type&VID_TYPE_MJPEG_ENCODER)?" Can encode MJPEG streams\n":""
);
sprintf( output+strlen(output), " Video Channels: %d\n", vid_cap.channels );
sprintf( output+strlen(output), " Audio Channels: %d\n", vid_cap.audios );
@ -1721,8 +1712,8 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
sprintf( output+strlen(output), " Name: %s\n", vid_src.name );
sprintf( output+strlen(output), " Channel: %d\n", vid_src.channel );
sprintf( output+strlen(output), " Flags: %d\n%s%s", vid_src.flags,
vid_src.flags&VIDEO_VC_TUNER?" Channel has a tuner\n":"",
vid_src.flags&VIDEO_VC_AUDIO?" Channel has audio\n":""
(vid_src.flags&VIDEO_VC_TUNER)?" Channel has a tuner\n":"",
(vid_src.flags&VIDEO_VC_AUDIO)?" Channel has audio\n":""
);
sprintf( output+strlen(output), " Type: %d - %s\n", vid_src.type,
vid_src.type==VIDEO_TYPE_TV?"TV":(
@ -2047,9 +2038,8 @@ int LocalCamera::PreCapture() {
int LocalCamera::Capture( Image &image ) {
Debug( 3, "Capturing" );
static uint8_t* buffer = NULL;
static uint8_t* directbuffer = NULL;
static int capture_frame = -1;
int buffer_bytesused = 0;
int capture_frame = -1;
int captures_per_frame = 1;
if ( channel_count > 1 )
@ -2059,7 +2049,6 @@ int LocalCamera::Capture( Image &image ) {
Warning( "Invalid Captures Per Frame setting: %d", captures_per_frame );
}
// Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer
if ( channel_prime ) {
#if ZM_HAS_V4L2
@ -2135,7 +2124,7 @@ int LocalCamera::Capture( Image &image ) {
Debug( 3, "Performing format conversion" );
/* Request a writeable buffer of the target image */
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
uint8_t* directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
if ( directbuffer == NULL ) {
Error("Failed requesting writeable buffer for the captured image.");
return -1;
@ -2153,7 +2142,13 @@ int LocalCamera::Capture( Image &image ) {
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
if ( conversion_type == 2 ) {
@ -2174,11 +2169,11 @@ int LocalCamera::Capture( Image &image ) {
}
return 1;
}
} // end int LocalCamera::Capture()
int LocalCamera::PostCapture()
{
Debug( 2, "Post-capturing" );
Debug( 4, "Post-capturing" );
// Requeue the buffer unless we need to switch or are a duplicate camera on a channel
if ( channel_count > 1 || channel_prime )
{

View File

@ -184,7 +184,7 @@ void Logger::initialise( const std::string &id, const Options &options ) {
StringVector targets = split( config.log_debug_target, "|" );
for ( unsigned int i = 0; i < targets.size(); i++ ) {
const std::string &target = targets[i];
if ( target == mId || target == "_"+mId || target == "_"+mIdRoot || target == "_"+mIdRoot || target == "" ) {
if ( target == mId || target == "_"+mId || target == "_"+mIdRoot || target == "" ) {
if ( config.log_debug_level > NOLOG ) {
tempLevel = config.log_debug_level;
if ( config.log_debug_file[0] ) {
@ -277,11 +277,10 @@ std::string Logger::strEnv( const std::string &name, const std::string &defaultV
}
char *Logger::getTargettedEnv( const std::string &name ) {
char *envPtr = NULL;
std::string envName;
envName = name+"_"+mId;
envPtr = getenv( envName.c_str() );
char *envPtr = getenv( envName.c_str() );
if ( !envPtr && mId != mIdRoot ) {
envName = name+"_"+mIdRoot;
envPtr = getenv( envName.c_str() );

View File

@ -26,7 +26,7 @@
inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) {
uint8_t* retptr;
#if HAVE_POSIX_MEMALIGN
if(posix_memalign((void**)&retptr,reqalignment,reqsize) != 0)
if ( posix_memalign((void**)&retptr,reqalignment,reqsize) != 0 )
return NULL;
return retptr;
@ -34,7 +34,7 @@ inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) {
uint8_t* alloc;
retptr = (uint8_t*)malloc(reqsize+reqalignment+sizeof(void*));
if(retptr == NULL)
if ( retptr == NULL )
return NULL;
alloc = retptr + sizeof(void*);
@ -58,20 +58,16 @@ inline void zm_freealigned(void* ptr) {
#endif
}
inline char *mempbrk( register const char *s, const char *accept, size_t limit )
{
if ( limit <= 0 || !s || !accept || !*accept )
return( 0 );
inline char *mempbrk( register const char *s, const char *accept, size_t limit ) {
if ( limit == 0 || !s || !accept || !*accept )
return 0;
register unsigned int i,j;
size_t acc_len = strlen( accept );
for ( i = 0; i < limit; s++, i++ )
{
for ( j = 0; j < acc_len; j++ )
{
if ( *s == accept[j] )
{
for ( i = 0; i < limit; s++, i++ ) {
for ( j = 0; j < acc_len; j++ ) {
if ( *s == accept[j] ) {
return( (char *)s );
}
}
@ -79,9 +75,8 @@ inline char *mempbrk( register const char *s, const char *accept, size_t limit )
return( 0 );
}
inline char *memstr( register const char *s, const char *n, size_t limit )
{
if ( limit <= 0 || !s || !n )
inline char *memstr( register const char *s, const char *n, size_t limit ) {
if ( limit == 0 || !s || !n )
return( 0 );
if ( !*n )
@ -90,14 +85,12 @@ inline char *memstr( register const char *s, const char *n, size_t limit )
register unsigned int i,j,k;
size_t n_len = strlen( n );
for ( i = 0; i < limit; i++, s++ )
{
for ( i = 0; i < limit; i++, s++ ) {
if ( *s != *n )
continue;
j = 1;
k = 1;
while ( true )
{
while ( true ) {
if ( k >= n_len )
return( (char *)s );
if ( s[j++] != n[k++] )
@ -107,36 +100,30 @@ inline char *memstr( register const char *s, const char *n, size_t limit )
return( 0 );
}
inline size_t memspn( register const char *s, const char *accept, size_t limit )
{
if ( limit <= 0 || !s || !accept || !*accept )
inline size_t memspn( register const char *s, const char *accept, size_t limit ) {
if ( limit == 0 || !s || !accept || !*accept )
return( 0 );
register unsigned int i,j;
size_t acc_len = strlen( accept );
for ( i = 0; i < limit; s++, i++ )
{
for ( i = 0; i < limit; s++, i++ ) {
register bool found = false;
for ( j = 0; j < acc_len; j++ )
{
if ( *s == accept[j] )
{
for ( j = 0; j < acc_len; j++ ) {
if ( *s == accept[j] ) {
found = true;
break;
}
}
if ( !found )
{
if ( !found ) {
return( i );
}
}
return( limit );
}
inline size_t memcspn( register const char *s, const char *reject, size_t limit )
{
if ( limit <= 0 || !s || !reject )
inline size_t memcspn( register const char *s, const char *reject, size_t limit ) {
if ( limit == 0 || !s || !reject )
return( 0 );
if ( !*reject )
@ -145,12 +132,9 @@ inline size_t memcspn( register const char *s, const char *reject, size_t limit
register unsigned int i,j;
size_t rej_len = strlen( reject );
for ( i = 0; i < limit; s++, i++ )
{
for ( j = 0; j < rej_len; j++ )
{
if ( *s == reject[j] )
{
for ( i = 0; i < limit; s++, i++ ) {
for ( j = 0; j < rej_len; j++ ) {
if ( *s == reject[j] ) {
return( i );
}
}

View File

@ -2974,26 +2974,24 @@ Debug(4, "Return from Capture (%d)", captureResult);
shared_data->last_write_time = image_buffer[index].timestamp->tv_sec;
image_count++;
} // end if captureResult
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
struct timeval now;
if ( !captureResult ) {
gettimeofday( &now, NULL );
} else {
now.tv_sec = image_buffer[index].timestamp->tv_sec;
}
fps = double(fps_report_interval)/(now.tv_sec-last_fps_time);
Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time );
//Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps );
Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps );
last_fps_time = now.tv_sec;
static char sql[ZM_SQL_SML_BUFSIZ];
snprintf( sql, sizeof(sql), "UPDATE Monitors SET CaptureFPS='%.2lf' WHERE Id=%d", fps, id );
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
}
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
time_t now = image_buffer[index].timestamp->tv_sec;
// If we are too fast, we get div by zero. This seems to happen in the case of audio packets.
if ( now != last_fps_time ) {
// # of images per interval / the amount of time it took
fps = double(fps_report_interval)/(now-last_fps_time);
Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time );
//Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps );
Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps );
last_fps_time = now;
static char sql[ZM_SQL_SML_BUFSIZ];
snprintf( sql, sizeof(sql), "UPDATE Monitors SET CaptureFPS='%.2lf' WHERE Id=%d", fps, id );
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
}
}
} // end if captureResult
}
// Icon: I'm not sure these should be here. They have nothing to do with capturing

View File

@ -330,7 +330,7 @@ protected:
MonitorLink **linked_monitors;
public:
Monitor( int p_id );
explicit Monitor( int p_id );
// OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info.
//bool OurCheckAlarms( Zone *zone, const Image *pImage );

View File

@ -498,7 +498,8 @@ void MonitorStream::runStream() {
if ( type == STREAM_JPEG )
fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" );
int last_read_index = monitor->image_buffer_count;
// point to end which is theoretically not a valid value because all indexes are % image_buffer_count
unsigned int last_read_index = monitor->image_buffer_count;
time_t stream_start_time;
time( &stream_start_time );
@ -557,6 +558,8 @@ void MonitorStream::runStream() {
Debug( 2, "Assigned temporary buffer" );
}
}
} else {
Debug(2, "Not using playback_buffer");
} // end if connkey & playback_buffer
float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs)
@ -576,7 +579,7 @@ void MonitorStream::runStream() {
gettimeofday( &now, NULL );
if ( connkey ) {
//Debug(2, "checking command Queue for connkey: %d", connkey );
Debug(2, "checking command Queue for connkey: %d", connkey );
while(checkCommandQueue()) {
Debug(2, "Have checking command Queue for connkey: %d", connkey );
got_command = true;
@ -657,26 +660,29 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
delayed = false;
replay_rate = ZM_RATE_BASE;
}
}
if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index ) {
int index = monitor->shared_data->last_write_index%monitor->image_buffer_count;
} // end if ( buffered_playback && delayed )
if ( last_read_index != monitor->shared_data->last_write_index ) {
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary
last_read_index = monitor->shared_data->last_write_index;
//Debug( 1, "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer );
Debug( 1, "index: %d: frame_mod: %d frame count: %d", index, frame_mod, frame_count );
if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) {
if ( !paused && !delayed ) {
// Send the next frame
Monitor::Snapshot *snap = &monitor->image_buffer[index];
//Debug(2, "sending Frame.");
if ( !sendFrame( snap->image, snap->timestamp ) ) {
Debug(2, "sendFrame failed, quiting.");
zm_terminate = true;
}
// Perhaps we should use NOW instead.
memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) );
//frame_sent = true;
temp_read_index = temp_write_index;
}
}
} // end if should send frame
if ( buffered_playback ) {
if ( monitor->shared_data->valid ) {
if ( monitor->image_buffer[index].timestamp->tv_sec ) {
@ -706,21 +712,29 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
}
} // end if buffered playback
frame_count++;
}
} else {
Debug(2,"Waiting for capture");
} // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
Debug(2, "Sleeping for (%d)", sleep_time);
usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) );
usleep( sleep_time );
if ( ttl ) {
if ( (now.tv_sec - stream_start_time) > ttl ) {
Debug(2, "now(%d) - start(%d) > ttl(%d) break", now.tv_sec, stream_start_time, ttl);
break;
}
}
if ( (TV_2_FLOAT( now ) - last_frame_sent) > max_secs_since_last_sent_frame ) {
if ( ! last_frame_sent ) {
// If we didn't capture above, because frame_mod was bad? Then last_frame_sent will not have a value.
last_frame_sent = now.tv_sec;
Warning( "no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d) ", frame_mod, frame_count );
} else if ( (TV_2_FLOAT( now ) - last_frame_sent) > max_secs_since_last_sent_frame ) {
Error( "Terminating, last frame sent time %f secs more than maximum of %f", TV_2_FLOAT( now ) - last_frame_sent, max_secs_since_last_sent_frame );
break;
}
} // end while
if ( buffered_playback ) {
Debug( 1, "Cleaning swap files from %s", swap_path );
struct stat stat_buf;

View File

@ -55,9 +55,9 @@ class MonitorStream : public StreamBase {
bool sendFrame( const char *filepath, struct timeval *timestamp );
bool sendFrame( Image *image, struct timeval *timestamp );
void processCommand( const CmdMsg *msg );
void SingleImage( int scale=100 );
void SingleImageRaw( int scale=100 );
void SingleImageZip( int scale=100 );
void SingleImage( int scale=100 );
void SingleImageRaw( int scale=100 );
void SingleImageZip( int scale=100 );
public:
MonitorStream() : playback_buffer( 0 ), delayed( false ), frame_count( 0 ) {

View File

@ -62,6 +62,7 @@ void VideoStream::SetupFormat( ) {
AVFormatContext *s= avformat_alloc_context();
if(!s) {
Fatal( "avformat_alloc_context failed %d \"%s\"", (size_t)ofc, av_err2str((size_t)ofc) );
return;
}
AVOutputFormat *oformat;
@ -88,7 +89,7 @@ void VideoStream::SetupFormat( ) {
if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (!s->priv_data) {
if ( !(s->priv_data) ) {
Fatal( "Could not allocate private data for output format." );
}
#if LIBAVFORMAT_VERSION_CHECK(52, 92, 0, 92, 0)
@ -211,39 +212,52 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
Debug( 1, "Allocated stream" );
AVCodecContext *c = ost->codec;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
codec_context = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(codec_context, ost->codecpar);
#else
codec_context = ost->codec;
#endif
c->codec_id = codec->id;
c->codec_type = codec->type;
codec_context->codec_id = codec->id;
codec_context->codec_type = codec->type;
c->pix_fmt = strcmp( "mjpeg", ofc->oformat->name ) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P;
codec_context->pix_fmt = strcmp( "mjpeg", ofc->oformat->name ) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P;
if ( bitrate <= 100 ) {
// Quality based bitrate control (VBR). Scale is 1..31 where 1 is best.
// This gets rid of artifacts in the beginning of the movie; and well, even quality.
c->flags |= CODEC_FLAG_QSCALE;
c->global_quality = FF_QP2LAMBDA * (31 - (31 * (bitrate / 100.0)));
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
codec_context->flags |= AV_CODEC_FLAG_QSCALE;
#else
codec_context->flags |= CODEC_FLAG_QSCALE;
#endif
codec_context->global_quality = FF_QP2LAMBDA * (31 - (31 * (bitrate / 100.0)));
} else {
c->bit_rate = bitrate;
codec_context->bit_rate = bitrate;
}
/* resolution must be a multiple of two */
c->width = width;
c->height = height;
codec_context->width = width;
codec_context->height = height;
/* time base: this is the fundamental unit of time (in seconds) in terms
of which frame timestamps are represented. for fixed-fps content,
timebase should be 1/framerate and timestamp increments should be
identically 1. */
c->time_base.den = frame_rate;
c->time_base.num = 1;
codec_context->time_base.den = frame_rate;
codec_context->time_base.num = 1;
Debug( 1, "Will encode in %d fps.", c->time_base.den );
Debug( 1, "Will encode in %d fps.", codec_context->time_base.den );
/* emit one intra frame every second */
c->gop_size = frame_rate;
codec_context->gop_size = frame_rate;
// some formats want stream headers to be separate
if ( of->flags & AVFMT_GLOBALHEADER )
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
codec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else
codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
} else {
Fatal( "of->video_codec == AV_CODEC_ID_NONE" );
}
@ -273,39 +287,33 @@ const char *VideoStream::MimeType( ) const {
}
void VideoStream::OpenStream( ) {
int avRet;
int ret;
/* now that all the parameters are set, we can open the
video codecs and allocate the necessary encode buffers */
if ( ost ) {
AVCodecContext *c = ost->codec;
/* open the codec */
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
if ( (avRet = avcodec_open( c, codec )) < 0 )
if ( (ret = avcodec_open( codec_context, codec )) < 0 )
#else
if ( (avRet = avcodec_open2( c, codec, 0 )) < 0 )
if ( (ret = avcodec_open2( codec_context, codec, 0 )) < 0 )
#endif
{
Fatal( "Could not open codec. Error code %d \"%s\"", avRet, av_err2str( avRet ) );
Fatal( "Could not open codec. Error code %d \"%s\"", ret, av_err2str(ret) );
}
Debug( 1, "Opened codec" );
/* allocate the encoded raw picture */
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
opicture = av_frame_alloc( );
#else
opicture = avcodec_alloc_frame( );
#endif
opicture = zm_av_frame_alloc( );
if ( !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 );
int size = av_image_get_buffer_size( codec_context->pix_fmt, codec_context->width, codec_context->height, 1 );
#else
int size = avpicture_get_size( c->pix_fmt, c->width, c->height );
int size = avpicture_get_size( codec_context->pix_fmt, codec_context->width, codec_context->height );
#endif
uint8_t *opicture_buf = (uint8_t *)av_malloc( size );
@ -315,17 +323,17 @@ void VideoStream::OpenStream( ) {
}
#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);
opicture_buf, codec_context->pix_fmt, codec_context->width, codec_context->height, 1);
#else
avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt,
c->width, c->height );
avpicture_fill( (AVPicture *)opicture, opicture_buf, codec_context->pix_fmt,
codec_context->width, codec_context->height );
#endif
/* 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
output format */
tmp_opicture = NULL;
if ( c->pix_fmt != pf ) {
if ( codec_context->pix_fmt != pf ) {
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
tmp_opicture = av_frame_alloc( );
#else
@ -335,9 +343,9 @@ void VideoStream::OpenStream( ) {
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 );
int size = av_image_get_buffer_size( pf, codec_context->width, codec_context->height,1 );
#else
int size = avpicture_get_size( pf, c->width, c->height );
int size = avpicture_get_size( pf, codec_context->width, codec_context->height );
#endif
uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc( size );
if ( !tmp_opicture_buf ) {
@ -347,17 +355,16 @@ void VideoStream::OpenStream( ) {
#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);
codec_context->width, codec_context->height, 1);
#else
avpicture_fill( (AVPicture *)tmp_opicture,
tmp_opicture_buf, pf, c->width, c->height );
tmp_opicture_buf, pf, codec_context->width, codec_context->height );
#endif
}
}
/* open the output file, if needed */
if ( !(of->flags & AVFMT_NOFILE) ) {
int ret;
#if LIBAVFORMAT_VERSION_CHECK(53, 15, 0, 21, 0)
ret = avio_open2( &ofc->pb, filename, AVIO_FLAG_WRITE, NULL, NULL );
#elif LIBAVFORMAT_VERSION_CHECK(52, 102, 0, 102, 0)
@ -375,7 +382,12 @@ void VideoStream::OpenStream( ) {
}
video_outbuf = NULL;
#if LIBAVFORMAT_VERSION_CHECK(57, 0, 0, 0, 0)
if (codec_context->codec_type == AVMEDIA_TYPE_VIDEO &&
codec_context->codec_id == AV_CODEC_ID_RAWVIDEO) {
#else
if ( !(of->flags & AVFMT_RAWPICTURE) ) {
#endif
/* allocate output buffer */
/* XXX: API change will be done */
// TODO: Make buffer dynamic.
@ -393,9 +405,9 @@ void VideoStream::OpenStream( ) {
#endif
#if !LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 4, 0)
int ret = av_write_header( ofc );
ret = av_write_header( ofc );
#else
int ret = avformat_write_header( ofc, NULL );
ret = avformat_write_header( ofc, NULL );
#endif
if ( ret < 0 ) {
@ -406,9 +418,15 @@ void VideoStream::OpenStream( ) {
VideoStream::VideoStream( const char *in_filename, const char *in_format, int bitrate, double frame_rate, int colours, int subpixelorder, int width, int height ) :
filename(in_filename),
format(in_format),
opicture(NULL),
tmp_opicture(NULL),
video_outbuf(NULL),
video_outbuf_size(0),
last_pts( -1 ),
streaming_thread(0),
do_streaming(true),
add_timestamp(false),
timestamp(0),
buffer_copy(NULL),
buffer_copy_lock(new pthread_mutex_t),
buffer_copy_size(0),
@ -446,6 +464,8 @@ VideoStream::VideoStream( const char *in_filename, const char *in_format, int bi
if ( pthread_mutex_init( buffer_copy_lock, NULL ) != 0 ) {
Fatal("pthread_mutex_init failed");
}
codec_context = NULL;
}
VideoStream::~VideoStream( ) {
@ -481,7 +501,7 @@ VideoStream::~VideoStream( ) {
/* close each codec */
if ( ost ) {
avcodec_close( ost->codec );
avcodec_close( codec_context );
av_free( opicture->data[0] );
av_frame_free( &opicture );
if ( tmp_opicture ) {
@ -560,21 +580,19 @@ double VideoStream::EncodeFrame( const uint8_t *buffer, int buffer_size, bool _a
}
double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size, bool add_timestamp, unsigned int timestamp ) {
if ( codec_context->pix_fmt != pf ) {
#ifdef HAVE_LIBSWSCALE
static struct SwsContext *img_convert_ctx = 0;
#endif // HAVE_LIBSWSCALE
AVCodecContext *c = ost->codec;
if ( c->pix_fmt != pf ) {
memcpy( tmp_opicture->data[0], buffer, buffer_size );
#ifdef HAVE_LIBSWSCALE
if ( !img_convert_ctx ) {
img_convert_ctx = sws_getCachedContext( NULL, c->width, c->height, pf, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL );
img_convert_ctx = sws_getCachedContext( NULL, codec_context->width, codec_context->height, pf, codec_context->width, codec_context->height, codec_context->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL );
if ( !img_convert_ctx )
Panic( "Unable to initialise image scaling context" );
}
sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, c->height, opicture->data, opicture->linesize );
sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, codec_context->height, opicture->data, opicture->linesize );
#else // HAVE_LIBSWSCALE
Fatal( "swscale is required for MPEG mode" );
#endif // HAVE_LIBSWSCALE
@ -586,7 +604,13 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
AVPacket *pkt = packet_buffers[packet_index];
av_init_packet( pkt );
int got_packet = 0;
#if LIBAVFORMAT_VERSION_CHECK(57, 0, 0, 0, 0)
if (codec_context->codec_type == AVMEDIA_TYPE_VIDEO &&
codec_context->codec_id == AV_CODEC_ID_RAWVIDEO) {
#else
if ( of->flags & AVFMT_RAWPICTURE ) {
#endif
#if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2)
pkt->flags |= AV_PKT_FLAG_KEY;
#else
@ -597,19 +621,34 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
pkt->size = sizeof (AVPicture);
got_packet = 1;
} else {
opicture_ptr->pts = c->frame_number;
opicture_ptr->quality = c->global_quality;
opicture_ptr->pts = codec_context->frame_number;
opicture_ptr->quality = codec_context->global_quality;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// Put encoder into flushing mode
avcodec_send_frame(codec_context, opicture_ptr);
int ret = avcodec_receive_packet(codec_context, pkt);
if ( ret < 0 ) {
if ( AVERROR_EOF != ret ) {
Error("ERror encoding video (%d) (%s)", ret,
av_err2str(ret));
}
} else {
got_packet = 1;
}
#else
#if LIBAVFORMAT_VERSION_CHECK(54, 1, 0, 2, 100)
int ret = avcodec_encode_video2( c, pkt, opicture_ptr, &got_packet );
int ret = avcodec_encode_video2( codec_context, pkt, opicture_ptr, &got_packet );
if ( ret != 0 ) {
Fatal( "avcodec_encode_video2 failed with errorcode %d \"%s\"", ret, av_err2str( ret ) );
}
#else
int out_size = avcodec_encode_video( c, video_outbuf, video_outbuf_size, opicture_ptr );
int out_size = avcodec_encode_video( codec_context, video_outbuf, video_outbuf_size, opicture_ptr );
got_packet = out_size > 0 ? 1 : 0;
pkt->data = got_packet ? video_outbuf : NULL;
pkt->size = got_packet ? out_size : 0;
#endif
#endif
if ( got_packet ) {
// if ( c->coded_frame->key_frame )
@ -622,12 +661,12 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
// }
if ( pkt->pts != (int64_t)AV_NOPTS_VALUE ) {
pkt->pts = av_rescale_q( pkt->pts, c->time_base, ost->time_base );
pkt->pts = av_rescale_q( pkt->pts, codec_context->time_base, ost->time_base );
}
if ( pkt->dts != (int64_t)AV_NOPTS_VALUE ) {
pkt->dts = av_rescale_q( pkt->dts, c->time_base, ost->time_base );
pkt->dts = av_rescale_q( pkt->dts, codec_context->time_base, ost->time_base );
}
pkt->duration = av_rescale_q( pkt->duration, c->time_base, ost->time_base );
pkt->duration = av_rescale_q( pkt->duration, codec_context->time_base, ost->time_base );
pkt->stream_index = ost->index;
}
}
@ -658,8 +697,12 @@ void *VideoStream::StreamingThreadCallback(void *ctx){
VideoStream* videoStream = reinterpret_cast<VideoStream*>(ctx);
const uint64_t nanosecond_multiplier = 1000000000;
uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->ost->codec->time_base.num) / (videoStream->ost->codec->time_base.den) );
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->codec_context->time_base.num) / (videoStream->codec_context->time_base.den) );
#else
uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->codec_context->time_base.num) / (videoStream->codec_context->time_base.den) );
#endif
uint64_t frame_count = 0;
timespec start_time;
clock_gettime(CLOCK_MONOTONIC, &start_time);

View File

@ -24,11 +24,9 @@
#if HAVE_LIBAVCODEC
class VideoStream
{
class VideoStream {
protected:
struct MimeData
{
struct MimeData {
const char *format;
const char *mime_type;
};
@ -46,6 +44,7 @@ protected:
AVOutputFormat *of;
AVFormatContext *ofc;
AVStream *ost;
AVCodecContext *codec_context;
AVCodec *codec;
AVFrame *opicture;
AVFrame *tmp_opicture;
@ -55,9 +54,9 @@ protected:
pthread_t streaming_thread;
bool do_streaming;
uint8_t *buffer_copy;
bool add_timestamp;
unsigned int timestamp;
uint8_t *buffer_copy;
pthread_mutex_t *buffer_copy_lock;
int buffer_copy_size;
int buffer_copy_used;

View File

@ -25,6 +25,8 @@
using namespace std;
ZMPacket::ZMPacket( AVPacket *p ) {
frame = NULL;
image = NULL;
av_init_packet( &packet );
if ( zm_av_packet_ref( &packet, p ) < 0 ) {
Error("error refing packet");
@ -33,6 +35,8 @@ ZMPacket::ZMPacket( AVPacket *p ) {
}
ZMPacket::ZMPacket( AVPacket *p, struct timeval *t ) {
frame = NULL;
image = NULL;
av_init_packet( &packet );
if ( zm_av_packet_ref( &packet, p ) < 0 ) {
Error("error refing packet");

View File

@ -39,7 +39,7 @@ class ZMPacket {
public:
AVPacket *av_packet() { return &packet; }
ZMPacket( AVPacket *packet, struct timeval *timestamp );
ZMPacket( AVPacket *packet );
explicit ZMPacket( AVPacket *packet );
~ZMPacket();
};

View File

@ -39,14 +39,14 @@ protected:
double _1_m;
static int CompareYX( const void *p1, const void *p2 ) {
const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2;
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
if ( e1->min_y == e2->min_y )
return( int(e1->min_x - e2->min_x) );
else
return( int(e1->min_y - e2->min_y) );
}
static int CompareX( const void *p1, const void *p2 ) {
const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2;
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
return( int(e1->min_x - e2->min_x) );
}
};

View File

@ -42,7 +42,9 @@ RemoteCamera::RemoteCamera(
host( p_host ),
port( p_port ),
path( p_path ),
hp( 0 )
hp( 0 ),
mNeedAuth(false),
mAuthenticator(NULL)
{
if ( path[0] != '/' )
path = '/'+path;
@ -97,13 +99,13 @@ void RemoteCamera::Initialise() {
int RemoteCamera::Read( int fd, char *buf, int size ) {
int ReceivedBytes = 0;
int bytes;
while ( ReceivedBytes < size ) {
// recv blocks until we get data, but it may be of ARBITRARY LENGTH and INCOMPLETE
int bytes_to_recv = size - ReceivedBytes;
if ( SOCKET_BUF_SIZE < bytes_to_recv )
bytes_to_recv = SOCKET_BUF_SIZE;
bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags
//Debug(3, "Aiming to receive %d of %d bytes", bytes_to_recv, size );
int bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags
if ( bytes <= 0 ) {
Error("RemoteCamera::Read Recv error. Closing Socket\n");
return -1;

View File

@ -87,7 +87,8 @@ public:
virtual void Terminate() = 0;
virtual int Connect() = 0;
virtual int Disconnect() = 0;
virtual int PreCapture() = 0;
virtual int PreCapture() { return 0; };
virtual int PrimeCapture() { return 0; };
virtual int Capture( Image &image ) = 0;
virtual int PostCapture() = 0;
virtual int CaptureAndRecord( Image &image, timeval recording, char* event_directory )=0;

View File

@ -588,10 +588,6 @@ int RemoteCameraHttp::GetResponse()
else
#endif // HAVE_LIBPCRE
{
if ( method == REGEXP )
{
Warning( "Unable to use netcam regexps as not compiled with libpcre" );
}
static const char *http_match = "HTTP/";
static const char *connection_match = "Connection:";
static const char *content_length_match = "Content-length:";

View File

@ -67,6 +67,7 @@ RemoteCameraNVSocket::RemoteCameraNVSocket(
timeout.tv_sec = 0;
timeout.tv_usec = 0;
subpixelorder = ZM_SUBPIX_ORDER_BGR;
if ( capture ) {
Initialise();
@ -97,43 +98,39 @@ void RemoteCameraNVSocket::Initialise() {
}
int RemoteCameraNVSocket::Connect() {
int port_num = atoi(port.c_str());
//struct addrinfo *p;
struct sockaddr_in servaddr;
bzero( &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(atoi(port.c_str()));
struct sockaddr_in servaddr;
bzero( &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(port_num);
sd = socket(AF_INET, SOCK_STREAM, 0);
sd = socket(AF_INET, SOCK_STREAM, 0);
//for(p = hp; p != NULL; p = p->ai_next) {
//sd = socket( p->ai_family, p->ai_socktype, p->ai_protocol );
if ( sd < 0 ) {
Warning("Can't create socket: %s", strerror(errno) );
//continue;
return -1;
}
//if ( connect( sd, p->ai_addr, p->ai_addrlen ) < 0 ) {
if ( connect( sd, (struct sockaddr *)&servaddr , sizeof(servaddr) ) < 0 ) {
close(sd);
sd = -1;
Warning("Can't connect to socket mid: %d : %s", monitor_id, strerror(errno) );
return -1;
//continue;
//}
/* If we got here, we must have connected successfully */
//break;
//sd = socket( p->ai_family, p->ai_socktype, p->ai_protocol );
if ( sd < 0 ) {
Warning("Can't create socket: %s", strerror(errno) );
//continue;
return -1;
}
//if ( p == NULL ) {
//Error("Unable to connect to the remote camera, aborting");
//return( -1 );
//}
//if ( connect( sd, p->ai_addr, p->ai_addrlen ) < 0 ) {
if ( connect( sd, (struct sockaddr *)&servaddr , sizeof(servaddr) ) < 0 ) {
close(sd);
sd = -1;
Debug( 3, "Connected to host, socket = %d", sd );
return( sd );
Warning("Can't connect to socket mid: %d : %s", monitor_id, strerror(errno) );
return -1;
}
//if ( p == NULL ) {
//Error("Unable to connect to the remote camera, aborting");
//return( -1 );
//}
Debug( 3, "Connected to host:%d, socket = %d", port_num, sd );
return sd;
}
int RemoteCameraNVSocket::Disconnect() {
@ -144,132 +141,33 @@ int RemoteCameraNVSocket::Disconnect() {
}
int RemoteCameraNVSocket::SendRequest( std::string request ) {
Debug( 2, "Sending request: %s", request.c_str() );
Debug( 4, "Sending request: %s", request.c_str() );
if ( write( sd, request.data(), request.length() ) < 0 ) {
Error( "Can't write: %s", strerror(errno) );
Disconnect();
return( -1 );
}
Debug( 3, "Request sent" );
Debug( 4, "Request sent" );
return( 0 );
}
/* Return codes are as follows:
* -1 means there was an error
* 0 means no bytes were returned but there wasn't actually an error.
* > 0 is the # of bytes read.
*/
int RemoteCameraNVSocket::ReadData( Buffer &buffer, unsigned int bytes_expected ) {
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(sd, &rfds);
struct timeval temp_timeout = timeout;
int n_found = select(sd+1, &rfds, NULL, NULL, &temp_timeout);
if ( n_found == 0 ) {
Debug( 4, "Select timed out timeout was %d secs %d usecs", temp_timeout.tv_sec, temp_timeout.tv_usec );
int error = 0;
socklen_t len = sizeof(error);
int retval = getsockopt(sd, SOL_SOCKET, SO_ERROR, &error, &len);
if ( retval != 0 ) {
Debug(1, "error getting socket error code %s", strerror(retval));
}
if ( error != 0 ) {
return -1;
}
// Why are we disconnecting? It's just a timeout, meaning that data wasn't available.
//Disconnect();
return 0;
} else if ( n_found < 0 ) {
Error("Select error: %s", strerror(errno));
return -1;
}
unsigned int total_bytes_to_read = 0;
if ( bytes_expected ) {
total_bytes_to_read = bytes_expected;
} else {
if ( ioctl( sd, FIONREAD, &total_bytes_to_read ) < 0 ) {
Error( "Can't ioctl(): %s", strerror(errno) );
return( -1 );
}
if ( total_bytes_to_read == 0 ) {
if ( mode == SINGLE_IMAGE ) {
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt( sd, SOL_SOCKET, SO_ERROR, &error, &len );
if(retval != 0 ) {
Debug( 1, "error getting socket error code %s", strerror(retval) );
}
if (error != 0) {
return -1;
}
// Case where we are grabbing a single jpg, but no content-length was given, so the expectation is that we read until close.
return( 0 );
}
// If socket is closed locally, then select will fail, but if it is closed remotely
// then we have an exception on our socket.. but no data.
Debug( 3, "Socket closed remotely" );
//Disconnect(); // Disconnect is done outside of ReadData now.
return( -1 );
}
// There can be lots of bytes available. I've seen 4MB or more. This will vastly inflate our buffer size unnecessarily.
if ( total_bytes_to_read > ZM_NETWORK_BUFSIZ ) {
total_bytes_to_read = ZM_NETWORK_BUFSIZ;
Debug(3, "Just getting 32K" );
} else {
Debug(3, "Just getting %d", total_bytes_to_read );
}
} // end if bytes_expected or not
Debug( 3, "Expecting %d bytes", total_bytes_to_read );
int total_bytes_read = 0;
do {
int bytes_read = buffer.read_into( sd, total_bytes_to_read );
if ( bytes_read < 0 ) {
Error( "Read error: %s", strerror(errno) );
return( -1 );
} else if ( bytes_read == 0 ) {
Debug( 2, "Socket closed" );
//Disconnect(); // Disconnect is done outside of ReadData now.
return( -1 );
} else if ( (unsigned int)bytes_read < total_bytes_to_read ) {
Error( "Incomplete read, expected %d, got %d", total_bytes_to_read, bytes_read );
return( -1 );
}
Debug( 3, "Read %d bytes", bytes_read );
total_bytes_read += bytes_read;
total_bytes_to_read -= bytes_read;
} while ( total_bytes_to_read );
Debug( 4, buffer );
return( total_bytes_read );
}
int RemoteCameraNVSocket::PreCapture() {
int RemoteCameraNVSocket::PrimeCapture() {
if ( sd < 0 ) {
Connect();
if ( sd < 0 ) {
Error( "Unable to connect to camera" );
return( -1 );
}
mode = SINGLE_IMAGE;
buffer.clear();
}
struct image_def {
uint16_t width;
uint16_t height;
uint16_t type;
};
struct image_def image_def;
buffer.clear();
struct image_def {
uint16_t width;
uint16_t height;
uint16_t type;
};
struct image_def image_def;
if ( SendRequest("GetImageParams") < 0 ) {
if ( SendRequest("GetImageParams\n") < 0 ) {
Error( "Unable to send request" );
Disconnect();
return -1;
@ -289,20 +187,28 @@ struct image_def image_def;
}
int RemoteCameraNVSocket::Capture( Image &image ) {
if ( SendRequest("GetNextImage") < 0 ) {
if ( SendRequest("GetNextImage\n") < 0 ) {
Warning( "Unable to capture image, retrying" );
return( 1 );
return 0;
}
if ( Read( sd, buffer, imagesize ) < imagesize ) {
Warning( "Unable to capture image, retrying" );
return( 1 );
return 0;
}
uint32_t end;
if ( Read(sd, (char *) &end , sizeof(end)) < 0 ) {
Warning( "Unable to capture image, retrying" );
return 0;
}
if ( end != 0xFFFFFFFF) {
Warning("End Bytes Failed\n");
return 0;
}
image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
return( 0 );
return 1;
}
int RemoteCameraNVSocket::PostCapture()
{
int RemoteCameraNVSocket::PostCapture() {
return( 0 );
}

View File

@ -67,7 +67,7 @@ bool p_record_audio );
int SendRequest( std::string );
int ReadData( Buffer &buffer, unsigned int bytes_expected=0 );
int GetResponse();
int PreCapture();
int PrimeCapture();
int Capture( Image &image );
int PostCapture();
int CaptureAndRecord( Image &image, timeval recording, char* event_directory ) {return(0);};

View File

@ -332,7 +332,7 @@ int RtpCtrlThread::run()
timeout = false;
last_receive = time(NULL);
}
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ )
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); ++iter )
{
if ( UdpInetSocket *socket = dynamic_cast<UdpInetSocket *>(*iter) )
{

View File

@ -94,7 +94,7 @@ int RtpDataThread::run()
mStop = true;
break;
}
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ )
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); ++iter )
{
if ( UdpInetServer *socket = dynamic_cast<UdpInetServer *>(*iter) )
{

View File

@ -36,8 +36,7 @@ int RtspThread::smMinDataPort = 0;
int RtspThread::smMaxDataPort = 0;
RtspThread::PortSet RtspThread::smAssignedPorts;
bool RtspThread::sendCommand( std::string message )
{
bool RtspThread::sendCommand( std::string message ) {
if ( mNeedAuth ) {
StringVector parts = split( message, " " );
if (parts.size() > 1)
@ -46,20 +45,15 @@ bool RtspThread::sendCommand( std::string message )
message += stringtf( "User-Agent: ZoneMinder/%s\r\n", ZM_VERSION );
message += stringtf( "CSeq: %d\r\n\r\n", ++mSeq );
Debug( 2, "Sending RTSP message: %s", message.c_str() );
if ( mMethod == RTP_RTSP_HTTP )
{
if ( mMethod == RTP_RTSP_HTTP ) {
message = base64Encode( message );
Debug( 2, "Sending encoded RTSP message: %s", message.c_str() );
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() )
{
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( false );
}
}
else
{
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() )
{
} else {
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( false );
}
@ -67,77 +61,60 @@ bool RtspThread::sendCommand( std::string message )
return( true );
}
bool RtspThread::recvResponse( std::string &response )
{
bool RtspThread::recvResponse( std::string &response ) {
if ( mRtspSocket.recv( response ) < 0 )
Error( "Recv failed; %s", strerror(errno) );
Debug( 2, "Received RTSP response: %s (%zd bytes)", response.c_str(), response.size() );
float respVer = 0;
respCode = -1;
char respText[ZM_NETWORK_BUFSIZ];
if ( sscanf( response.c_str(), "RTSP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 )
{
if ( isalnum(response[0]) )
{
if ( sscanf( response.c_str(), "RTSP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) {
if ( isalnum(response[0]) ) {
Error( "Response parse failure in '%s'", response.c_str() );
}
else
{
} else {
Error( "Response parse failure, %zd bytes follow", response.size() );
if ( response.size() )
Hexdump( Logger::ERROR, response.data(), min(response.size(),16) );
}
return( false );
}
if ( respCode == 401)
{
if ( respCode == 401) {
Debug( 2, "Got 401 access denied response code, check WWW-Authenticate header and retry");
mAuthenticator->checkAuthResponse(response);
mNeedAuth = true;
return( false );
}
else if ( respCode != 200 )
{
} else if ( respCode != 200 ) {
Error( "Unexpected response code %d, text is '%s'", respCode, respText );
return( false );
}
return( true );
}
int RtspThread::requestPorts()
{
if ( !smMinDataPort )
{
int RtspThread::requestPorts() {
if ( !smMinDataPort ) {
char sql[ZM_SQL_SML_BUFSIZ];
strncpy( sql, "select Id from Monitors where Function != 'None' and Type = 'Remote' and Protocol = 'rtsp' and Method = 'rtpUni' order by Id asc", sizeof(sql) );
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
MYSQL_RES *result = mysql_store_result( &dbconn );
if ( !result )
{
if ( !result ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
int nMonitors = mysql_num_rows( result );
int position = 0;
if ( nMonitors )
{
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ )
{
if ( nMonitors ) {
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {
int id = atoi(dbrow[0]);
if ( mId == id )
{
if ( mId == id ) {
position = i;
break;
}
}
}
else
{
} else {
// Minor hack for testing when not strictly enabled
nMonitors = 1;
position = 0;
@ -148,11 +125,9 @@ int RtspThread::requestPorts()
smMaxDataPort = smMinDataPort + portRange - 1;
Debug( 2, "Assigned RTP port range is %d-%d", smMinDataPort, smMaxDataPort );
}
for ( int i = smMinDataPort; i <= smMaxDataPort; i++ )
{
for ( int i = smMinDataPort; i <= smMaxDataPort; i++ ) {
PortSet::const_iterator iter = smAssignedPorts.find( i );
if ( iter == smAssignedPorts.end() )
{
if ( iter == smAssignedPorts.end() ) {
smAssignedPorts.insert( i );
return( i );
}
@ -161,8 +136,7 @@ int RtspThread::requestPorts()
return( -1 );
}
void RtspThread::releasePorts( int port )
{
void RtspThread::releasePorts( int port ) {
if ( port > 0 )
smAssignedPorts.erase( port );
}
@ -185,8 +159,7 @@ RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol,
mStop( false )
{
mUrl = mProtocol+"://"+mHost+":"+mPort;
if ( !mPath.empty() )
{
if ( !mPath.empty() ) {
if ( mPath[0] == '/' )
mUrl += mPath;
else
@ -208,10 +181,8 @@ RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol,
mAuthenticator = new zm::Authenticator(parts[0], "");
}
RtspThread::~RtspThread()
{
if ( mFormatContext )
{
RtspThread::~RtspThread() {
if ( mFormatContext ) {
#if LIBAVFORMAT_VERSION_CHECK(52, 96, 0, 96, 0)
avformat_free_context( mFormatContext );
#else
@ -219,16 +190,14 @@ RtspThread::~RtspThread()
#endif
mFormatContext = NULL;
}
if ( mSessDesc )
{
if ( mSessDesc ) {
delete mSessDesc;
mSessDesc = NULL;
}
delete mAuthenticator;
}
int RtspThread::run()
{
int RtspThread::run() {
std::string message;
std::string response;
@ -246,8 +215,7 @@ int RtspThread::run()
bool authTried = false;
if ( mMethod == RTP_RTSP_HTTP )
{
if ( mMethod == RTP_RTSP_HTTP ) {
if ( !mRtspSocket2.connect( mHost.c_str(), mPort.c_str() ) )
Fatal( "Unable to connect auxiliary RTSP/HTTP socket" );
//Select select( 0.25 );
@ -271,13 +239,11 @@ int RtspThread::run()
message += "Accept: application/x-rtsp-tunnelled\r\n";
message += "\r\n";
Debug( 2, "Sending HTTP message: %s", message.c_str() );
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() )
{
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( -1 );
}
if ( mRtspSocket.recv( response ) < 0 )
{
if ( mRtspSocket.recv( response ) < 0 ) {
Error( "Recv failed; %s", strerror(errno) );
return( -1 );
}
@ -285,14 +251,10 @@ int RtspThread::run()
Debug( 2, "Received HTTP response: %s (%zd bytes)", response.c_str(), response.size() );
float respVer = 0;
respCode = -1;
if ( sscanf( response.c_str(), "HTTP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 )
{
if ( isalnum(response[0]) )
{
if ( sscanf( response.c_str(), "HTTP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) {
if ( isalnum(response[0]) ) {
Error( "Response parse failure in '%s'", response.c_str() );
}
else
{
} else {
Error( "Response parse failure, %zd bytes follow", response.size() );
if ( response.size() )
Hexdump( Logger::ERROR, response.data(), min(response.size(),16) );
@ -313,8 +275,7 @@ int RtspThread::run()
} while (respCode == 401 && !authTried);
if ( respCode != 200 )
{
if ( respCode != 200 ) {
Error( "Unexpected response code %d, text is '%s'", respCode, respText );
return( -1 );
}
@ -327,8 +288,7 @@ int RtspThread::run()
message += "Content-Type: application/x-rtsp-tunnelled\r\n";
message += "\r\n";
Debug( 2, "Sending HTTP message: %s", message.c_str() );
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() )
{
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( -1 );
}
@ -383,17 +343,14 @@ int RtspThread::run()
if( sdpStart == std::string::npos )
return( -1 );
if ( mRtspDescribe )
{
if ( mRtspDescribe ) {
std::string DescHeader = response.substr( 0,sdpStart );
Debug( 1, "Processing DESCRIBE response header '%s'", DescHeader.c_str() );
lines = split( DescHeader, "\r\n" );
for ( size_t i = 0; i < lines.size(); i++ )
{
for ( size_t i = 0; i < lines.size(); i++ ) {
// If the device sends us a url value for Content-Base in the response header, we should use that instead
if ( ( lines[i].size() > 13 ) && ( lines[i].substr( 0, 13 ) == "Content-Base:" ) )
{
if ( ( lines[i].size() > 13 ) && ( lines[i].substr( 0, 13 ) == "Content-Base:" ) ) {
mUrl = trimSpaces( lines[i].substr( 13 ) );
Info("Received new Content-Base in DESCRIBE response header. Updated device Url to: '%s'", mUrl.c_str() );
break;
@ -406,13 +363,10 @@ int RtspThread::run()
std::string sdp = response.substr( sdpStart );
Debug( 1, "Processing SDP '%s'", sdp.c_str() );
try
{
try {
mSessDesc = new SessionDescriptor( mUrl, sdp );
mFormatContext = mSessDesc->generateFormatContext();
}
catch( const Exception &e )
{
} catch( const Exception &e ) {
Error( e.getMessage().c_str() );
return( -1 );
}
@ -436,10 +390,8 @@ int RtspThread::run()
_AVCODECID codecId;
if ( mFormatContext->nb_streams >= 1 )
{
for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ )
{
if ( mFormatContext->nb_streams >= 1 ) {
for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) {
SessionDescriptor::MediaDescriptor *mediaDesc = mSessDesc->getStream( i );
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO )
@ -449,12 +401,9 @@ int RtspThread::run()
{
// Check if control Url is absolute or relative
controlUrl = mediaDesc->getControlUrl();
if (std::equal(trackUrl.begin(), trackUrl.end(), controlUrl.begin()))
{
if (std::equal(trackUrl.begin(), trackUrl.end(), controlUrl.begin())) {
trackUrl = controlUrl;
}
else
{
} else {
if ( *trackUrl.rbegin() != '/') {
trackUrl += "/" + controlUrl;
} else {
@ -470,8 +419,7 @@ int RtspThread::run()
}
}
switch( mMethod )
{
switch( mMethod ) {
case RTP_UNICAST :
{
localPorts[0] = requestPorts();
@ -508,10 +456,8 @@ int RtspThread::run()
int timeout = 0;
char transport[256] = "";
for ( size_t i = 0; i < lines.size(); i++ )
{
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) )
{
for ( size_t i = 0; i < lines.size(); i++ ) {
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) ) {
StringVector sessionLine = split( lines[i].substr(9), ";" );
session = trimSpaces( sessionLine[0] );
if ( sessionLine.size() == 2 )
@ -536,41 +482,31 @@ int RtspThread::run()
std::string distribution = "";
unsigned long ssrc = 0;
StringVector parts = split( transport, ";" );
for ( size_t i = 0; i < parts.size(); i++ )
{
for ( size_t i = 0; i < parts.size(); i++ ) {
if ( parts[i] == "unicast" || parts[i] == "multicast" )
distribution = parts[i];
else if ( startsWith( parts[i], "server_port=" ) )
{
else if ( startsWith( parts[i], "server_port=" ) ) {
method = "RTP/UNICAST";
StringVector subparts = split( parts[i], "=" );
StringVector ports = split( subparts[1], "-" );
remotePorts[0] = strtol( ports[0].c_str(), NULL, 10 );
remotePorts[1] = strtol( ports[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[i], "interleaved=" ) )
{
} else if ( startsWith( parts[i], "interleaved=" ) ) {
method = "RTP/RTSP";
StringVector subparts = split( parts[i], "=" );
StringVector channels = split( subparts[1], "-" );
remoteChannels[0] = strtol( channels[0].c_str(), NULL, 10 );
remoteChannels[1] = strtol( channels[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[i], "port=" ) )
{
} else if ( startsWith( parts[i], "port=" ) ) {
method = "RTP/MULTICAST";
StringVector subparts = split( parts[i], "=" );
StringVector ports = split( subparts[1], "-" );
localPorts[0] = strtol( ports[0].c_str(), NULL, 10 );
localPorts[1] = strtol( ports[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[i], "destination=" ) )
{
} else if ( startsWith( parts[i], "destination=" ) ) {
StringVector subparts = split( parts[i], "=" );
localHost = subparts[1];
}
else if ( startsWith( parts[i], "ssrc=" ) )
{
} else if ( startsWith( parts[i], "ssrc=" ) ) {
StringVector subparts = split( parts[i], "=" );
ssrc = strtoll( subparts[1].c_str(), NULL, 16 );
}
@ -592,13 +528,11 @@ int RtspThread::run()
lines = split( response, "\r\n" );
std::string rtpInfo;
for ( size_t i = 0; i < lines.size(); i++ )
{
for ( size_t i = 0; i < lines.size(); i++ ) {
if ( ( lines[i].size() > 9 ) && ( lines[i].substr( 0, 9 ) == "RTP-Info:" ) )
rtpInfo = trimSpaces( lines[i].substr( 9 ) );
// Check for a timeout again. Some rtsp devices don't send a timeout until after the PLAY command is sent
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) && ( timeout == 0 ) )
{
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) && ( timeout == 0 ) ) {
StringVector sessionLine = split( lines[i].substr(9), ";" );
if ( sessionLine.size() == 2 )
sscanf( trimSpaces( sessionLine[1] ).c_str(), "timeout=%d", &timeout );
@ -610,31 +544,22 @@ int RtspThread::run()
int seq = 0;
unsigned long rtpTime = 0;
StringVector streams;
if ( rtpInfo.empty() )
{
if ( rtpInfo.empty() ) {
Debug( 1, "RTP Info Empty. Starting values for Sequence and Rtptime shall be zero.");
}
else
{
} else {
Debug( 2, "Got RTP Info %s", rtpInfo.c_str() );
// More than one stream can be included in the RTP Info
streams = split( rtpInfo.c_str(), "," );
for ( size_t i = 0; i < streams.size(); i++ )
{
for ( size_t i = 0; i < streams.size(); i++ ) {
// We want the stream that matches the trackUrl we are using
if ( streams[i].find(controlUrl.c_str()) != std::string::npos )
{
if ( streams[i].find(controlUrl.c_str()) != std::string::npos ) {
// Parse the sequence and rtptime values
parts = split( streams[i].c_str(), ";" );
for ( size_t j = 0; j < parts.size(); j++ )
{
if ( startsWith( parts[j], "seq=" ) )
{
for ( size_t j = 0; j < parts.size(); j++ ) {
if ( startsWith( parts[j], "seq=" ) ) {
StringVector subparts = split( parts[j], "=" );
seq = strtol( subparts[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[j], "rtptime=" ) )
{
} else if ( startsWith( parts[j], "rtptime=" ) ) {
StringVector subparts = split( parts[j], "=" );
rtpTime = strtol( subparts[1].c_str(), NULL, 10 );
}
@ -651,8 +576,7 @@ int RtspThread::run()
time_t now;
message = "GET_PARAMETER "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n";
switch( mMethod )
{
switch( mMethod ) {
case RTP_UNICAST :
{
RtpSource *source = new RtpSource( mId, "", localPorts[0], mHost, remotePorts[0], ssrc, seq, rtpClock, rtpTime, codecId );
@ -663,13 +587,11 @@ int RtspThread::run()
rtpDataThread.start();
rtpCtrlThread.start();
while( !mStop )
{
while( !mStop ) {
now = time(NULL);
// Send a keepalive message if the server supports this feature and we are close to the timeout expiration
Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepalive, timeout, now, lastKeepalive, (now-lastKeepalive) );
if ( sendKeepalive && (timeout > 0) && ((now-lastKeepalive) > (timeout-5)) )
{
if ( sendKeepalive && (timeout > 0) && ((now-lastKeepalive) > (timeout-5)) ) {
if ( !sendCommand( message ) )
return( -1 );
lastKeepalive = now;
@ -721,11 +643,9 @@ Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepali
Buffer buffer( ZM_NETWORK_BUFSIZ );
std::string keepaliveMessage = "OPTIONS "+mUrl+" RTSP/1.0\r\n";
std::string keepaliveResponse = "RTSP/1.0 200 OK\r\n";
while ( !mStop && select.wait() >= 0 )
{
while ( !mStop && select.wait() >= 0 ) {
Select::CommsList readable = select.getReadable();
if ( readable.size() == 0 )
{
if ( readable.size() == 0 ) {
Error( "RTSP timed out" );
break;
}
@ -735,23 +655,19 @@ Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepali
buffer.append( tempBuffer, nBytes );
Debug( 4, "Read %zd bytes on sd %d, %d total", nBytes, mRtspSocket.getReadDesc(), buffer.size() );
while( buffer.size() > 0 )
{
if ( buffer[0] == '$' )
{
while( buffer.size() > 0 ) {
if ( buffer[0] == '$' ) {
if ( buffer.size() < 4 )
break;
unsigned char channel = buffer[1];
unsigned short len = ntohs( *((unsigned short *)(buffer+2)) );
Debug( 4, "Got %d bytes left, expecting %d byte packet on channel %d", buffer.size(), len, channel );
if ( (unsigned short)buffer.size() < (len+4) )
{
if ( (unsigned short)buffer.size() < (len+4) ) {
Debug( 4, "Missing %d bytes, rereading", (len+4)-buffer.size() );
break;
}
if ( channel == remoteChannels[0] )
{
if ( channel == remoteChannels[0] ) {
Debug( 4, "Got %d bytes on data channel %d, packet length is %d", buffer.size(), channel, len );
Hexdump( 4, (char *)buffer, 16 );
rtpDataThread.recvPacket( buffer+4, len );

View File

@ -31,8 +31,7 @@
#include <set>
#include <map>
class RtspThread : public Thread
{
class RtspThread : public Thread {
public:
typedef enum { RTP_UNICAST, RTP_MULTICAST, RTP_RTSP, RTP_RTSP_HTTP } RtspMethod;
typedef enum { UNDEFINED, UNICAST, MULTICAST } RtspDist;

View File

@ -26,7 +26,11 @@
namespace zm {
Authenticator::Authenticator(std::string &username, std::string password) {
Authenticator::Authenticator( const std::string &username, const std::string &password) :
fCnonce( "0a4f113b" ),
fUsername(username),
fPassword(password)
{
#ifdef HAVE_GCRYPT_H
// Special initialisation for libgcrypt
if ( !gcry_check_version( GCRYPT_VERSION ) )
@ -38,10 +42,7 @@ Authenticator::Authenticator(std::string &username, std::string password) {
#endif // HAVE_GCRYPT_H
fAuthMethod = AUTH_UNDEFINED;
fUsername = username;
fPassword = password;
nc = 1;
fCnonce = "0a4f113b";
}
Authenticator::~Authenticator() {
@ -96,13 +97,11 @@ void Authenticator::authHandleHeader(std::string headerData)
}
}
std::string Authenticator::quote(std::string src)
{
std::string Authenticator::quote( const std::string &src ) {
return replaceAll(replaceAll(src, "\\", "\\\\"), "\"", "\\\"");
}
std::string Authenticator::getAuthHeader(std::string method, std::string uri)
{
std::string Authenticator::getAuthHeader(std::string method, std::string uri) {
std::string result = "Authorization: ";
if (fAuthMethod == AUTH_BASIC)
{

View File

@ -37,7 +37,7 @@ namespace zm {
enum AuthMethod { AUTH_UNDEFINED = 0, AUTH_BASIC = 1, AUTH_DIGEST = 2 };
class Authenticator {
public:
Authenticator(std::string &username, std::string password);
Authenticator(const std::string &username, const std::string &password);
virtual ~Authenticator();
void reset();
@ -60,7 +60,7 @@ private:
std::string fQop;
std::string fUsername;
std::string fPassword;
std::string quote( std::string src );
std::string quote( const std::string &src );
int nc;
};

View File

@ -159,8 +159,7 @@ SessionDescriptor::SessionDescriptor( const std::string &url, const std::string
MediaDescriptor *currMedia = 0;
StringVector lines = split( sdp, "\r\n" );
for ( StringVector::const_iterator iter = lines.begin(); iter != lines.end(); iter++ )
{
for ( StringVector::const_iterator iter = lines.begin(); iter != lines.end(); ++iter ) {
std::string line = *iter;
if ( line.empty() )
break;
@ -276,48 +275,26 @@ SessionDescriptor::SessionDescriptor( const std::string &url, const std::string
{
StringVector attr3Tokens = split( attr2Tokens[i], "=" );
//Info( "Name = %s, Value = %s", attr3Tokens[0].c_str(), attr3Tokens[1].c_str() );
if ( attr3Tokens[0] == "profile-level-id" )
{
}
else if ( attr3Tokens[0] == "config" )
{
}
else if ( attr3Tokens[0] == "sprop-parameter-sets" )
{
if ( attr3Tokens[0] == "profile-level-id" ) {
} else if ( attr3Tokens[0] == "config" ) {
} else if ( attr3Tokens[0] == "sprop-parameter-sets" ) {
size_t t = attr2Tokens[i].find("=");
char *c = (char *)attr2Tokens[i].c_str() + t + 1;
Debug(4, "sprop-parameter-sets value %s", c);
currMedia->setSprops(std::string(c));
}
else if ( attr3Tokens[0] == "sprop-parameter-sets" )
{
size_t t = attr2Tokens[i].find("=");
char *c = (char *)attr2Tokens[i].c_str() + t + 1;
Debug(4, "sprop-parameter-sets value %s", c);
currMedia->setSprops(std::string(c));
}
else
{
} else {
Debug( 3, "Ignoring SDP fmtp attribute '%s' for media '%s'", attr3Tokens[0].c_str(), currMedia->getType().c_str() )
}
}
}
}
else if ( attrName == "mpeg4-iod" )
{
} else if ( attrName == "mpeg4-iod" ) {
// a=mpeg4-iod: "data:application/mpeg4-iod;base64,AoEAAE8BAf73AQOAkwABQHRkYXRhOmFwcGxpY2F0aW9uL21wZWc0LW9kLWF1O2Jhc2U2NCxBVGdCR3dVZkF4Y0F5U1FBWlFRTklCRUVrK0FBQWEyd0FBR3RzQVlCQkFFWkFwOERGUUJsQlFRTlFCVUFDN2dBQVBvQUFBRDZBQVlCQXc9PQQNAQUABAAAAAAAAAAAAAYJAQAAAAAAAAAAA0IAAkA+ZGF0YTphcHBsaWNhdGlvbi9tcGVnNC1iaWZzLWF1O2Jhc2U2NCx3QkFTZ1RBcUJYSmhCSWhRUlFVL0FBPT0EEgINAAACAAAAAAAAAAAFAwAAQAYJAQAAAAAAAAAA"
}
else if ( attrName == "mpeg4-esid" )
{
} else if ( attrName == "mpeg4-esid" ) {
// a=mpeg4-esid:201
}
else
{
} else {
Debug( 3, "Ignoring SDP attribute '%s' for media '%s'", line.c_str(), currMedia->getType().c_str() )
}
}
else
{
} else {
Debug( 3, "Ignoring general SDP attribute '%s'", line.c_str() );
}
break;
@ -369,8 +346,7 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
strncpy( formatContext->comment, mInfo.c_str(), sizeof(formatContext->comment) );
*/
//formatContext->nb_streams = mMediaList.size();
for ( unsigned int i = 0; i < mMediaList.size(); i++ )
{
for ( unsigned int i = 0; i < mMediaList.size(); i++ ) {
const MediaDescriptor *mediaDesc = mMediaList[i];
#if !LIBAVFORMAT_VERSION_CHECK(53, 10, 0, 17, 0)
AVStream *stream = av_new_stream( formatContext, i );
@ -379,62 +355,62 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
stream->id = i;
#endif
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
AVCodecContext *codec_context = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(codec_context, stream->codecpar);
#else
AVCodecContext *codec_context = stream->codec;
#endif
Debug( 1, "Looking for codec for %s payload type %d / %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() );
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( mediaDesc->getType() == "video" )
stream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
codec_context->codec_type = AVMEDIA_TYPE_VIDEO;
else if ( mediaDesc->getType() == "audio" )
stream->codec->codec_type = AVMEDIA_TYPE_AUDIO;
codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
else if ( mediaDesc->getType() == "application" )
stream->codec->codec_type = AVMEDIA_TYPE_DATA;
codec_context->codec_type = AVMEDIA_TYPE_DATA;
#else
if ( mediaDesc->getType() == "video" )
stream->codec->codec_type = CODEC_TYPE_VIDEO;
codec_context->codec_type = CODEC_TYPE_VIDEO;
else if ( mediaDesc->getType() == "audio" )
stream->codec->codec_type = CODEC_TYPE_AUDIO;
codec_context->codec_type = CODEC_TYPE_AUDIO;
else if ( mediaDesc->getType() == "application" )
stream->codec->codec_type = CODEC_TYPE_DATA;
codec_context->codec_type = CODEC_TYPE_DATA;
#endif
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
std::string codec_name;
#endif
if ( mediaDesc->getPayloadType() < PAYLOAD_TYPE_DYNAMIC )
{
if ( mediaDesc->getPayloadType() < PAYLOAD_TYPE_DYNAMIC ) {
// Look in static table
for ( unsigned int i = 0; i < (sizeof(smStaticPayloads)/sizeof(*smStaticPayloads)); i++ )
{
if ( smStaticPayloads[i].payloadType == mediaDesc->getPayloadType() )
{
for ( unsigned int i = 0; i < (sizeof(smStaticPayloads)/sizeof(*smStaticPayloads)); i++ ) {
if ( smStaticPayloads[i].payloadType == mediaDesc->getPayloadType() ) {
Debug( 1, "Got static payload type %d, %s", smStaticPayloads[i].payloadType, smStaticPayloads[i].payloadName );
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
codec_name = std::string( smStaticPayloads[i].payloadName );
#else
strncpy( stream->codec->codec_name, smStaticPayloads[i].payloadName, sizeof(stream->codec->codec_name) );;
strncpy( codec_context->codec_name, smStaticPayloads[i].payloadName, sizeof(codec_context->codec_name) );;
#endif
stream->codec->codec_type = smStaticPayloads[i].codecType;
stream->codec->codec_id = smStaticPayloads[i].codecId;
stream->codec->sample_rate = smStaticPayloads[i].clockRate;
codec_context->codec_type = smStaticPayloads[i].codecType;
codec_context->codec_id = smStaticPayloads[i].codecId;
codec_context->sample_rate = smStaticPayloads[i].clockRate;
break;
}
}
}
else
{
} else {
// Look in dynamic table
for ( unsigned int i = 0; i < (sizeof(smDynamicPayloads)/sizeof(*smDynamicPayloads)); i++ )
{
if ( smDynamicPayloads[i].payloadName == mediaDesc->getPayloadDesc() )
{
for ( unsigned int i = 0; i < (sizeof(smDynamicPayloads)/sizeof(*smDynamicPayloads)); i++ ) {
if ( smDynamicPayloads[i].payloadName == mediaDesc->getPayloadDesc() ) {
Debug( 1, "Got dynamic payload type %d, %s", mediaDesc->getPayloadType(), smDynamicPayloads[i].payloadName );
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
codec_name = std::string( smStaticPayloads[i].payloadName );
#else
strncpy( stream->codec->codec_name, smDynamicPayloads[i].payloadName, sizeof(stream->codec->codec_name) );;
strncpy( codec_context->codec_name, smDynamicPayloads[i].payloadName, sizeof(codec_context->codec_name) );;
#endif
stream->codec->codec_type = smDynamicPayloads[i].codecType;
stream->codec->codec_id = smDynamicPayloads[i].codecId;
stream->codec->sample_rate = mediaDesc->getClock();
codec_context->codec_type = smDynamicPayloads[i].codecType;
codec_context->codec_id = smDynamicPayloads[i].codecId;
codec_context->sample_rate = mediaDesc->getClock();
break;
}
}
@ -450,14 +426,13 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
//return( 0 );
}
if ( mediaDesc->getWidth() )
stream->codec->width = mediaDesc->getWidth();
codec_context->width = mediaDesc->getWidth();
if ( mediaDesc->getHeight() )
stream->codec->height = mediaDesc->getHeight();
if ( stream->codec->codec_id == AV_CODEC_ID_H264 && mediaDesc->getSprops().size())
{
codec_context->height = mediaDesc->getHeight();
if ( codec_context->codec_id == AV_CODEC_ID_H264 && mediaDesc->getSprops().size()) {
uint8_t start_sequence[]= { 0, 0, 1 };
stream->codec->extradata_size= 0;
stream->codec->extradata= NULL;
codec_context->extradata_size= 0;
codec_context->extradata= NULL;
char pvalue[1024], *value = pvalue;
strcpy(pvalue, mediaDesc->getSprops().c_str());
@ -482,22 +457,33 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
if (packet_size) {
uint8_t *dest =
(uint8_t *)av_malloc(packet_size + sizeof(start_sequence) +
stream->codec->extradata_size +
FF_INPUT_BUFFER_PADDING_SIZE);
codec_context->extradata_size +
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
AV_INPUT_BUFFER_PADDING_SIZE
#else
FF_INPUT_BUFFER_PADDING_SIZE
#endif
);
if(dest) {
if(stream->codec->extradata_size) {
if(codec_context->extradata_size) {
// av_realloc?
memcpy(dest, stream->codec->extradata, stream->codec->extradata_size);
av_free(stream->codec->extradata);
memcpy(dest, codec_context->extradata, codec_context->extradata_size);
av_free(codec_context->extradata);
}
memcpy(dest+stream->codec->extradata_size, start_sequence, sizeof(start_sequence));
memcpy(dest+stream->codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
memset(dest+stream->codec->extradata_size+sizeof(start_sequence)+
packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
memcpy(dest+codec_context->extradata_size, start_sequence, sizeof(start_sequence));
memcpy(dest+codec_context->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
memset(dest+codec_context->extradata_size+sizeof(start_sequence)+
packet_size, 0,
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
AV_INPUT_BUFFER_PADDING_SIZE
#else
FF_INPUT_BUFFER_PADDING_SIZE
#endif
);
stream->codec->extradata= dest;
stream->codec->extradata_size+= sizeof(start_sequence)+packet_size;
codec_context->extradata= dest;
codec_context->extradata_size+= sizeof(start_sequence)+packet_size;
// } else {
// av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!");
// return AVERROR(ENOMEM);

View File

@ -31,13 +31,11 @@
#include <string>
#include <vector>
class SessionDescriptor
{
class SessionDescriptor {
protected:
enum { PAYLOAD_TYPE_DYNAMIC=96 };
struct StaticPayloadDesc
{
struct StaticPayloadDesc {
int payloadType;
const char payloadName[6];
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
@ -50,8 +48,7 @@ protected:
int autoChannels;
};
struct DynamicPayloadDesc
{
struct DynamicPayloadDesc {
const char payloadName[32];
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
AVMediaType codecType;
@ -65,8 +62,7 @@ protected:
};
public:
class ConnInfo
{
class ConnInfo {
protected:
std::string mNetworkType;
std::string mAddressType;
@ -75,21 +71,19 @@ public:
int mNoAddresses;
public:
ConnInfo( const std::string &connInfo );
explicit ConnInfo( const std::string &connInfo );
};
class BandInfo
{
class BandInfo {
protected:
std::string mType;
int mValue;
public:
BandInfo( const std::string &bandInfo );
explicit BandInfo( const std::string &bandInfo );
};
class MediaDescriptor
{
class MediaDescriptor {
protected:
std::string mType;
int mPort;
@ -144,48 +138,38 @@ public:
{
return( mControlUrl );
}
void setControlUrl( const std::string &controlUrl )
{
void setControlUrl( const std::string &controlUrl ) {
mControlUrl = controlUrl;
}
const int getClock() const
{
const int getClock() const {
return( mClock );
}
void setClock( int clock )
{
void setClock( int clock ) {
mClock = clock;
}
void setFrameSize( int width, int height )
{
void setFrameSize( int width, int height ) {
mWidth = width;
mHeight = height;
}
int getWidth() const
{
int getWidth() const {
return( mWidth );
}
int getHeight() const
{
int getHeight() const {
return( mHeight );
}
void setSprops(const std::string props)
{
void setSprops(const std::string &props) {
mSprops = props;
}
const std::string getSprops() const
{
const std::string getSprops() const {
return ( mSprops );
}
const double getFrameRate() const
{
const double getFrameRate() const {
return( mFrameRate );
}
void setFrameRate( double frameRate )
{
void setFrameRate( double frameRate ) {
mFrameRate = frameRate;
}
};

View File

@ -32,8 +32,8 @@ protected:
public:
Storage();
Storage( MYSQL_ROW &dbrow );
Storage( unsigned int p_id );
explicit Storage( MYSQL_ROW &dbrow );
explicit Storage( unsigned int p_id );
~Storage();
unsigned int Id() const { return( id ); }

View File

@ -75,6 +75,7 @@ void StreamBase::updateFrameRate( double fps ) {
bool StreamBase::checkCommandQueue() {
if ( sd >= 0 ) {
Debug(2, "sd is (%d)", sd );
CmdMsg msg;
memset( &msg, 0, sizeof(msg) );
int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 );
@ -88,9 +89,12 @@ bool StreamBase::checkCommandQueue() {
//Error( "Partial message received, expected %d bytes, got %d", sizeof(msg), nbytes );
//}
else {
Debug(2, "Message length is (%d)", nbytes );
processCommand( &msg );
return( true );
}
} else {
Error("sd is < 0");
}
return( false );
}
@ -287,7 +291,7 @@ void StreamBase::openComms() {
if ( sd < 0 ) {
Fatal( "Can't create socket: %s", strerror(errno) );
} else {
Debug(3, "Have socket %d", sd );
Debug(1, "Have socket %d", sd );
}
length = snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", staticConfig.PATH_SOCKS.c_str(), connkey );
@ -295,6 +299,7 @@ void StreamBase::openComms() {
Warning("Socket path was truncated.");
length = sizeof(loc_sock_path)-1;
}
// Unlink before bind, in case it already exists
unlink( loc_sock_path );
if ( sizeof(loc_addr.sun_path) < length ) {
Error("Not enough space %d in loc_addr.sun_path for socket file %s", sizeof(loc_addr.sun_path), loc_sock_path );
@ -312,7 +317,7 @@ void StreamBase::openComms() {
rem_addr.sun_family = AF_UNIX;
} // end if connKey > 0
Debug(2, "comms open" );
}
} // end void StreamBase::openComms()
void StreamBase::closeComms() {
if ( connkey > 0 ) {
@ -323,10 +328,10 @@ void StreamBase::closeComms() {
if ( loc_sock_path[0] ) {
unlink( loc_sock_path );
}
if (lock_fd > 0) {
if ( lock_fd > 0 ) {
close(lock_fd); //close it rather than unlock it incase it got deleted.
unlink(sock_path_lock);
// You cannot unlink the lockfile. You have to leave a mess around. SUCKS
//unlink(sock_path_lock);
}
}
}

View File

@ -141,6 +141,8 @@ public:
#if HAVE_LIBAVCODEC
vid_stream = 0;
#endif // HAVE_LIBAVCODEC
last_frame_sent = 0.0;
msg = { 0, { 0 } };
}
virtual ~StreamBase();

View File

@ -32,8 +32,7 @@
#include <sys/thr.h>
#endif
class ThreadException : public Exception
{
class ThreadException : public Exception {
private:
#ifndef SOLARIS
pid_t pid() {
@ -55,12 +54,11 @@ private:
pthread_t pid() { return( pthread_self() ); }
#endif
public:
ThreadException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)pid() ) ) {
explicit ThreadException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)pid() ) ) {
}
};
class Mutex
{
class Mutex {
friend class Condition;
private:
@ -71,8 +69,7 @@ public:
~Mutex();
private:
pthread_mutex_t *getMutex()
{
pthread_mutex_t *getMutex() {
return( &mMutex );
}
@ -84,18 +81,15 @@ public:
bool locked();
};
class ScopedMutex
{
class ScopedMutex {
private:
Mutex &mMutex;
public:
ScopedMutex( Mutex &mutex ) : mMutex( mutex )
{
explicit ScopedMutex( Mutex &mutex ) : mMutex( mutex ) {
mMutex.lock();
}
~ScopedMutex()
{
~ScopedMutex() {
mMutex.unlock();
}
@ -164,8 +158,7 @@ public:
}
};
template <class T> class ThreadData
{
template <class T> class ThreadData {
private:
T mValue;
mutable bool mChanged;
@ -173,11 +166,11 @@ private:
mutable Condition mCondition;
public:
__attribute__((used)) ThreadData() : mCondition( mMutex )
{
__attribute__((used)) ThreadData() : mCondition( mMutex ) {
mChanged = false;
}
__attribute__((used)) ThreadData( T value ) : mValue( value ), mCondition( mMutex )
{
__attribute__((used)) ThreadData( T value ) : mValue( value ), mCondition( mMutex ) {
mChanged = false;
}
//~ThreadData() {}

View File

@ -27,11 +27,12 @@
#include <string.h>
#include <time.h>
#include "zm_utils.h"
User::User() {
username[0] = password[0] = 0;
enabled = false;
stream = events = control = monitors = system = PERM_NONE;
monitor_ids = 0;
}
User::User( MYSQL_ROW &dbrow ) {
@ -44,45 +45,41 @@ User::User( MYSQL_ROW &dbrow ) {
control = (Permission)atoi( dbrow[index++] );
monitors = (Permission)atoi( dbrow[index++] );
system = (Permission)atoi( dbrow[index++] );
monitor_ids = 0;
char *monitor_ids_str = dbrow[index++];
if ( monitor_ids_str && *monitor_ids_str ) {
monitor_ids = new int[strlen(monitor_ids_str)];
int n_monitor_ids = 0;
const char *ptr = monitor_ids_str;
do {
int id = 0;
while( isdigit( *ptr ) ) {
id *= 10;
id += *ptr-'0';
ptr++;
}
if ( id ) {
monitor_ids[n_monitor_ids++] = id;
if ( !*ptr )
break;
}
while ( !isdigit( *ptr ) )
ptr++;
} while( *ptr );
monitor_ids[n_monitor_ids] = 0;
StringVector ids = split(monitor_ids_str, ",");
for( StringVector::iterator i = ids.begin(); i < ids.end(); ++i ) {
monitor_ids.push_back( atoi( (*i).c_str()) );
}
}
}
User::~User() {
delete monitor_ids;
monitor_ids.clear();
}
void User::Copy( const User &u ) {
strncpy( username, u.username, sizeof(username)-1 );
strncpy( password, u.password, sizeof(password)-1 );
enabled = u.enabled;
stream = u.stream;
events = u.events;
control = u.control;
monitors = u.monitors;
system = u.system;
monitor_ids = u.monitor_ids;
}
bool User::canAccess( int monitor_id ) {
if ( !monitor_ids ) {
return( true );
}
for ( int i = 0; monitor_ids[i]; i++ ) {
if ( monitor_ids[i] == monitor_id ) {
return( true );
if ( monitor_ids.empty() )
return true;
for ( std::vector<int>::iterator i = monitor_ids.begin(); i != monitor_ids.end(); ++i ) {
if ( *i == monitor_id ) {
return true;
}
}
return( false );
return false;
}
// Function to load a user from username and password
@ -90,12 +87,12 @@ bool User::canAccess( int monitor_id ) {
User *zmLoadUser( const char *username, const char *password ) {
char sql[ZM_SQL_SML_BUFSIZ] = "";
char safer_username[65]; // current db username size is 32
char safer_password[129]; // current db password size is 64
// According to docs, size of safer_whatever must be 2*length+1 due to unicode conversions + null terminator.
mysql_real_escape_string(&dbconn, safer_username, username, strlen( username ) );
if ( password ) {
char safer_password[129]; // current db password size is 64
mysql_real_escape_string(&dbconn, safer_password, password, strlen( password ) );
snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Password = password('%s') and Enabled = 1", safer_username, safer_password );
} else {

View File

@ -36,8 +36,8 @@
#include <openssl/md5.h>
#endif // HAVE_L || HAVE_LIBCRYPTO
class User
{
#include <vector>
class User {
public:
typedef enum { PERM_NONE=1, PERM_VIEW, PERM_EDIT } Permission;
@ -50,12 +50,17 @@ protected:
Permission control;
Permission monitors;
Permission system;
int *monitor_ids;
std::vector<int> monitor_ids;
public:
User();
User( MYSQL_ROW &dbrow );
explicit User( MYSQL_ROW &dbrow );
~User();
User( User &u ) { Copy(u); }
void Copy( const User &u );
User operator=(const User &u) {
Copy(u); return *this;
}
const char *getUsername() const { return( username ); }
const char *getPassword() const { return( password ); }

View File

@ -49,8 +49,7 @@ std::string trimSet(std::string str, std::string trimset) {
return str.substr( startpos, endpos-startpos+1 );
}
std::string trimSpaces(std::string str)
{
std::string trimSpaces(std::string str) {
return trimSet(str, " \t");
}
@ -80,7 +79,7 @@ const std::string stringtf( const char *format, ... )
return( tempString );
}
const std::string stringtf( const std::string &format, ... )
const std::string stringtf( const std::string format, ... )
{
va_list ap;
char tempBuffer[8192];
@ -100,7 +99,7 @@ bool startsWith( const std::string &haystack, const std::string &needle )
return( haystack.substr( 0, needle.length() ) == needle );
}
StringVector split( const std::string &string, const std::string chars, int limit )
StringVector split( const std::string &string, const std::string &chars, int limit )
{
StringVector stringVector;
std::string tempString = string;
@ -134,7 +133,7 @@ StringVector split( const std::string &string, const std::string chars, int limi
return( stringVector );
}
const std::string join(const StringVector v, const char * delim ) {
const std::string join(const StringVector &v, const char * delim ) {
std::stringstream ss;
for(size_t i = 0; i < v.size(); ++i) {
@ -209,10 +208,9 @@ int split(const char* string, const char delim, std::vector<std::string>& items)
return -2;
std::string str(string);
size_t pos;
while(true) {
pos = str.find(delim);
size_t pos = str.find(delim);
items.push_back(str.substr(0, pos));
str.erase(0, pos+1);

View File

@ -33,11 +33,11 @@ std::string trimSet(std::string str, std::string trimset);
std::string replaceAll(std::string str, std::string from, std::string to);
const std::string stringtf( const char *format, ... );
const std::string stringtf( const std::string &format, ... );
const std::string stringtf( const std::string format, ... );
bool startsWith( const std::string &haystack, const std::string &needle );
StringVector split( const std::string &string, const std::string chars, int limit=0 );
const std::string join( const StringVector, const char * );
StringVector split( const std::string &string, const std::string &chars, int limit=0 );
const std::string join( const StringVector &, const char * );
const std::string base64Encode( const std::string &inString );

View File

@ -167,7 +167,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
video_out_ctx->time_base.den);
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
video_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else
video_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
}
Monitor::Orientation orientation = monitor->getOrientation();
@ -274,7 +278,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
if (audio_out_stream) {
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
audio_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
audio_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else
audio_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
}
}
} // end if audio_in_stream

View File

@ -204,7 +204,6 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
int diff_width = diff_image->Width();
uint8_t* diff_buff = (uint8_t*)diff_image->Buffer();
uint8_t* pdiff;
const uint8_t* ppoly;
unsigned int pixel_diff_count = 0;
@ -267,6 +266,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
int bx1 = bx-1;
int by1 = by-1;
Debug( 5, "Checking for filtered pixels" );
if ( bx > 1 || by > 1 ) {
// Now remove any pixels smaller than our filter size
@ -679,7 +679,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
}
}
ppoly = pg_image->Buffer( lo_x2, y );
const uint8_t* ppoly = pg_image->Buffer( lo_x2, y );
for ( int x = lo_x2; x <= hi_x2; x++, pdiff++, ppoly++ ) {
if ( !*ppoly ) {
*pdiff = BLACK;
@ -946,13 +946,9 @@ bool Zone::DumpSettings( char *output, bool /*verbose*/ ) {
void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsigned int* pixel_count, unsigned int* pixel_sum) {
uint32_t pixelsalarmed = 0;
uint32_t pixelsdifference = 0;
uint8_t *pdiff;
const uint8_t *ppoly;
uint8_t calc_max_pixel_threshold = 255;
unsigned int lo_y;
unsigned int hi_y;
unsigned int lo_x;
unsigned int hi_x;
if(max_pixel_threshold)
calc_max_pixel_threshold = max_pixel_threshold;
@ -960,12 +956,12 @@ void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsig
lo_y = polygon.LoY();
hi_y = polygon.HiY();
for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
lo_x = ranges[y].lo_x;
hi_x = ranges[y].hi_x;
unsigned int lo_x = ranges[y].lo_x;
unsigned int hi_x = ranges[y].hi_x;
Debug( 7, "Checking line %d from %d -> %d", y, lo_x, hi_x );
pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y );
ppoly = ppoly_image->Buffer( lo_x, y );
uint8_t *pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y );
const uint8_t *ppoly = ppoly_image->Buffer( lo_x, y );
for ( unsigned int x = lo_x; x <= hi_x; x++, pdiff++, ppoly++ ) {
if ( *ppoly && (*pdiff > min_pixel_threshold) && (*pdiff <= calc_max_pixel_threshold) ) {

View File

@ -161,7 +161,7 @@ int main(int argc, char *argv[]) {
Usage();
}
int modes = (device[0]?1:0 + host[0]?1:0 + file[0]?1:0 + (monitor_id > 0 ? 1 : 0));
int modes = ( (device[0]?1:0) + (host[0]?1:0) + (file[0]?1:0) + (monitor_id > 0 ? 1 : 0));
if ( modes > 1 ) {
fprintf(stderr, "Only one of device, host/port/path, file or monitor id allowed\n");
Usage();

View File

@ -1,353 +0,0 @@
//
// ZoneMinder Image File Writer Implementation, $Date$, $Revision$
// Copyright (C) 2001-2008 Philip Coombes
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
/*
=head1 NAME
zmf - The ZoneMinder Frame daemon
=head1 SYNOPSIS
zmf -m <monitor_id>
zmf --monitor <monitor_id>
zmf -h
zmf --help
zmf -v
zmf --version
=head1 DESCRIPTION
This is an optional daemon that can run in concert with the Analysis daemon and
whose function it is to actually write captured frames to disk. This frees up
the Analysis daemon to do more analysis (!) and so keep up with the Capture
daemon better. If it isn't running or dies then the Analysis daemon just writes
them itself.
=head1 OPTIONS
-m, --monitor_id - ID of the monitor to use
-h, --help - Display usage information
-v, --version - Print the installed version of ZoneMinder
=cut
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <getopt.h>
#include <signal.h>
#include "zm.h"
#include "zm_db.h"
#include "zm_signal.h"
#include "zm_monitor.h"
#include "zmf.h"
int OpenSocket( int monitor_id )
{
int sd = socket( AF_UNIX, SOCK_STREAM, 0);
if ( sd < 0 )
{
Error( "Can't create socket: %s", strerror(errno) );
return( -1 );
}
char sock_path[PATH_MAX] = "";
snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id );
if ( unlink( sock_path ) < 0 )
{
Warning( "Can't unlink '%s': %s", sock_path, strerror(errno) );
}
struct sockaddr_un addr;
strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) );
addr.sun_family = AF_UNIX;
if ( bind( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 )
{
Error( "Can't bind: %s", strerror(errno) );
exit( -1 );
}
if ( listen( sd, SOMAXCONN ) < 0 )
{
Error( "Can't listen: %s", strerror(errno) );
return( -1 );
}
struct sockaddr_un rem_addr;
socklen_t rem_addr_len = sizeof(rem_addr);
int new_sd = -1;
if ( (new_sd = accept( sd, (struct sockaddr *)&rem_addr, &rem_addr_len )) < 0 )
{
Error( "Can't accept: %s", strerror(errno) );
exit( -1 );
}
close( sd );
sd = new_sd;
Info( "Frame server socket open, awaiting images" );
return( sd );
}
int ReopenSocket( int &sd, int monitor_id )
{
close( sd );
return( sd = OpenSocket( monitor_id ) );
}
void Usage()
{
fprintf( stderr, "zmf -m <monitor_id>\n" );
fprintf( stderr, "Options:\n" );
fprintf( stderr, " -m, --monitor <monitor_id> : Specify which monitor to use\n" );
fprintf( stderr, " -h, --help : This screen\n" );
fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" );
exit( 0 );
}
int main( int argc, char *argv[] )
{
self = argv[0];
srand( getpid() * time( 0 ) );
int id = -1;
static struct option long_options[] = {
{"monitor", 1, 0, 'm'},
{"help", 0, 0, 'h'},
{"version", 0, 0, 'v'},
{0, 0, 0, 0}
};
while (1)
{
int option_index = 0;
int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index);
if (c == -1)
{
break;
}
switch (c)
{
case 'm':
id = atoi(optarg);
break;
case 'h':
case '?':
Usage();
break;
case 'v':
std::cout << ZM_VERSION << "\n";
exit(0);
default:
//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
break;
}
}
if (optind < argc)
{
fprintf( stderr, "Extraneous options, " );
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
Usage();
}
if ( id < 0 )
{
fprintf( stderr, "Bogus monitor %d\n", id );
Usage();
exit( 0 );
}
char log_id_string[16];
snprintf( log_id_string, sizeof(log_id_string), "m%d", id );
zmLoadConfig();
logInit( "zmf" );
hwcaps_detect();
Monitor *monitor = Monitor::Load( id, false, Monitor::QUERY );
if ( !monitor )
{
fprintf( stderr, "Can't find monitor with id of %d\n", id );
exit( -1 );
}
Storage *Storage = monitor->getStorage();
char capt_path[PATH_MAX];
char anal_path[PATH_MAX];
snprintf( capt_path, sizeof(capt_path), "%s/%d/%%s/%%0%dd-capture.jpg", Storage->Path(), monitor->Id(), config.event_image_digits );
snprintf( anal_path, sizeof(anal_path), "%s/%d/%%s/%%0%dd-analyse.jpg", Storage->Path(), monitor->Id(), config.event_image_digits );
zmSetDefaultTermHandler();
zmSetDefaultDieHandler();
sigset_t block_set;
sigemptyset( &block_set );
int sd = OpenSocket( monitor->Id() );
FrameHeader frame_header = { 0, 0, false, 0 };
//unsigned char *image_data = 0;
fd_set rfds;
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
while( 1 )
{
struct timeval temp_timeout = timeout;
FD_ZERO(&rfds);
FD_SET(sd, &rfds);
int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout );
if( n_found == 0 )
{
Debug( 1, "Select timed out" );
continue;
}
else if ( n_found < 0)
{
Error( "Select error: %s", strerror(errno) );
ReopenSocket( sd, monitor->Id() );
continue;
}
sigprocmask( SIG_BLOCK, &block_set, 0 );
int n_bytes = read( sd, &frame_header, sizeof(frame_header) );
if ( n_bytes != sizeof(frame_header) )
{
if ( n_bytes < 0 )
{
Error( "Can't read frame header: %s", strerror(errno) );
}
else if ( n_bytes > 0 )
{
Error( "Incomplete read of frame header, %d bytes only", n_bytes );
}
else
{
Warning( "Socket closed at remote end" );
}
ReopenSocket( sd, monitor->Id() );
continue;
}
Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length );
static unsigned char image_data[ZM_MAX_IMAGE_SIZE];
// Read for pipe and loop until bytes expected have been read or an error occurs
int bytes_read = 0;
do
{
n_bytes = read( sd, image_data+bytes_read, frame_header.image_length-bytes_read );
if (n_bytes < 0) break; // break on error
if (n_bytes < (int)frame_header.image_length)
{
// print some informational messages
if (bytes_read == 0)
{
Debug(4,"Image read : Short read %d bytes of %d expected bytes",n_bytes,frame_header.image_length);
}
else if (bytes_read+n_bytes == (int)frame_header.image_length)
{
Debug(5,"Image read : Read rest of short read: %d bytes read total of %d bytes",n_bytes,frame_header.image_length);
}
else
{
Debug(6,"Image read : continuing, read %d bytes (%d so far)", n_bytes, bytes_read+n_bytes);
}
}
bytes_read+= n_bytes;
} while (n_bytes>0 && (bytes_read < (ssize_t)frame_header.image_length) );
// Print errors if there was a problem
if ( n_bytes < 1 )
{
Error( "Only read %d bytes of %d\n", bytes_read, frame_header.image_length);
if ( n_bytes < 0 )
{
Error( "Can't read frame image data: %s", strerror(errno) );
}
else
{
Warning( "Socket closed at remote end" );
}
ReopenSocket( sd, monitor->Id() );
continue;
}
static char subpath[PATH_MAX] = "";
if ( config.use_deep_storage )
{
struct tm *time = localtime( &frame_header.event_time );
snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
}
else
{
snprintf( subpath, sizeof(subpath), "%ld", frame_header.event_id );
}
static char path[PATH_MAX] = "";
snprintf( path, sizeof(path), frame_header.alarm_frame?anal_path:capt_path, subpath, frame_header.frame_id );
Debug( 1, "Got image, writing to %s", path );
FILE *fd = 0;
if ( (fd = fopen( path, "w" )) < 0 )
{
Error( "Can't fopen '%s': %s", path, strerror(errno) );
exit( -1 );
}
if ( 0 == fwrite( image_data, frame_header.image_length, 1, fd ) )
{
Error( "Can't fwrite image data: %s", strerror(errno) );
exit( -1 );
}
fclose( fd );
sigprocmask( SIG_UNBLOCK, &block_set, 0 );
}
logTerm();
zmDbClose();
}

View File

@ -84,12 +84,6 @@ int main( int argc, const char *argv[] ) {
zmLoadConfig();
logInit( "zms" );
hwcaps_detect();
zmSetDefaultTermHandler();
zmSetDefaultDieHandler();
const char *query = getenv( "QUERY_STRING" );
if ( query ) {
@ -175,6 +169,14 @@ int main( int argc, const char *argv[] ) {
} // end foreach parm
} // end if query
char log_id_string[32] = "zms";
if ( monitor_id ) {
snprintf(log_id_string, sizeof(log_id_string), "zms_m%d", monitor_id);
} else {
snprintf(log_id_string, sizeof(log_id_string), "zms_e%d", event_id);
}
logInit( log_id_string );
if ( config.opt_use_auth ) {
User *user = 0;
@ -205,6 +207,10 @@ int main( int argc, const char *argv[] ) {
ValidateAccess( user, monitor_id );
}
hwcaps_detect();
zmSetDefaultTermHandler();
zmSetDefaultDieHandler();
setbuf( stdout, 0 );
if ( nph ) {
fprintf( stdout, "HTTP/1.0 200 OK\r\n" );

View File

@ -693,8 +693,7 @@ int main( int argc, char *argv[] ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
int n_monitors = mysql_num_rows( result );
Debug( 1, "Got %d monitors", n_monitors );
Debug( 1, "Got %d monitors", mysql_num_rows( result ) );
printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" );
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {

View File

@ -8,6 +8,13 @@ exit;
fi
DEBUILD=`which debuild`;
if [ "$DEBUILD" == "" ]; then
echo "You must install the devscripts package. Try sudo apt-get install devscripts";
exit;
fi
for i in "$@"
do
case $i in

View File

@ -37,6 +37,8 @@ if ( $$opts{protocol} eq 'https' ) {
die "https requires a server_name";
}
$VirtualHostPorts = ' *:443';
} else {
$VirtualHostPorts = ' *:80';
}

View File

@ -137,6 +137,17 @@ $statusData = array(
//'Path' => array( 'postFunc' => 'getEventPath' ),
),
),
'frames' => array(
'permission' => 'Events',
'table' => 'Frames',
'selector' => 'EventId',
'elements' => array(
'EventId' => true,
'FrameId' => true,
'Type' => true,
'Delta' => true,
),
),
'frame' => array(
'permission' => 'Events',
'table' => 'Frames',

View File

@ -34,17 +34,13 @@ public function beforeFilter() {
public function index() {
$this->Event->recursive = -1;
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
if (!empty($allowedMonitors))
{
$mon_options = array('Event.MonitorId' => $allowedMonitors);
}
else
{
$mon_options='';
}
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
if (!empty($allowedMonitors)) {
$mon_options = array('Event.MonitorId' => $allowedMonitors);
} else {
$mon_options='';
}
if ($this->request->params['named']) {
$this->FilterComponent = $this->Components->load('Filter');
@ -81,7 +77,6 @@ public function beforeFilter() {
//$thumbData = $this->createThumbnail($value['Event']['Id']);
$thumbData = "";
$events[$key]['thumbData'] = $thumbData;
}
$this->set(compact('events'));

View File

@ -35,22 +35,24 @@ public function beforeFilter() {
* @return void
*/
public function index() {
$this->Monitor->recursive = 0;
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
$this->Monitor->recursive = 0;
if (!empty($allowedMonitors))
{
$options = array('conditions'=>array('Monitor.Id'=> $allowedMonitors));
if ($this->request->params['named']) {
$this->FilterComponent = $this->Components->load('Filter');
$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
} else {
$conditions = array();
}
else
{
$options='';
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
if (!empty($allowedMonitors)) {
$conditions['Monitor.Id' ] = $allowedMonitors;
}
$monitors = $this->Monitor->find('all',$options);
$this->set(array(
'monitors' => $monitors,
'_serialize' => array('monitors')
));
$monitors = $this->Monitor->find('all',array('conditions'=>$conditions));
$this->set(array(
'monitors' => $monitors,
'_serialize' => array('monitors')
));
}
/**
@ -122,7 +124,7 @@ public function beforeFilter() {
if (!$this->Monitor->exists($id)) {
throw new NotFoundException(__('Invalid monitor'));
}
if ($this->Session->Read('systemPermission') != 'Edit')
if ($this->Session->Read('monitorPermission') != 'Edit')
{
throw new UnauthorizedException(__('Insufficient privileges'));
return;

View File

@ -9,6 +9,7 @@ class Event {
'StorageId',
'Name',
'DiskSpace',
'SaveJPEGs',
);
public function __construct( $IdOrRow = null ) {
$row = NULL;

View File

@ -14,6 +14,9 @@ private $defaults = array(
'Width' => null,
'Height' => null,
'Orientation' => null,
'AnalysisFPSLimit' => null,
'AnalysisFPS' => null,
'CaptureFPS' => null,
);
private $control_fields = array(
'Name' => '',
@ -184,11 +187,13 @@ private $control_fields = array(
}
public function getStreamSrc( $args, $querySep='&amp;' ) {
$streamSrc = ZM_BASE_PROTOCOL.'://';
if ( isset($this->{'ServerId'}) and $this->{'ServerId'} ) {
$Server = new Server( $this->{'ServerId'} );
$streamSrc = ZM_BASE_PROTOCOL.'://'.$Server->Hostname();
$streamSrc .= $Server->Hostname();
} else {
$streamSrc = ZM_BASE_URL;
$streamSrc .= $_SERVER['HTTP_HOST'];
}
if ( ZM_MIN_STREAMING_PORT )
$streamSrc .= ':'. (ZM_MIN_STREAMING_PORT+$this->{'Id'});

View File

@ -134,14 +134,14 @@ function dbQuery( $sql, $params=NULL ) {
} else {
$result = $dbConn->query( $sql );
}
if ( 0 ) {
if ( 1 ) {
if ( $params )
Warning("SQL: $sql" . implode(',',$params) . ' rows: '.$result->rowCount() );
else
Warning("SQL: $sql: rows:" . $result->rowCount() );
}
} catch(PDOException $e) {
Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . $params?implode(',',$params):'' );
Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . ($params?implode(',',$params):'') );
}
return( $result );
}

View File

@ -28,13 +28,13 @@ if ( version_compare( phpversion(), '4.3.0', '<') ) {
}
# We are requiring these because this file is getting included from the api, which hasn't already included them.
require_once( 'logger.php' );
require_once( 'database.php' );
require_once('logger.php');
require_once('database.php');
function userLogin( $username, $password='', $passwordHashed=false ) {
global $user, $cookies;
$sql = 'SELECT * FROM Users WHERE Enabled = 1';
$sql = 'SELECT * FROM Users WHERE Enabled=1';
$sql_values = NULL;
if ( ZM_AUTH_TYPE == 'builtin' ) {
if ( $passwordHashed ) {
@ -44,7 +44,7 @@ function userLogin( $username, $password='', $passwordHashed=false ) {
}
$sql_values = array( $username, $password );
} else {
$sql .= ' AND Username = ?';
$sql .= ' AND Username=?';
$sql_values = array( $username );
}
$_SESSION['username'] = $username;
@ -138,26 +138,27 @@ function getAuthUser( $auth ) {
$authHash = md5( $authKey );
if ( $auth == $authHash ) {
return( $user );
return $user;
}
} // end foreach hour
} // end foreach user
} // end if using auth hash
Error( "Unable to authenticate user from auth hash '$auth'" );
return( false );
}
} // end getAuthUser($auth)
function generateAuthHash( $useRemoteAddr ) {
if ( ZM_OPT_USE_AUTH and ZM_AUTH_RELAY == 'hashed' and isset($_SESSION['username']) and $_SESSION['passwordHash'] ) {
# regenerate a hash at half the liftetime of a hash, an hour is 3600 so half is 1800
if ( ( ! isset($_SESSION['AuthHash']) ) or ( $_SESSION['AuthHashGeneratedAt'] < time() - ( ZM_AUTH_HASH_TTL * 1800 ) ) ) {
$time = time();
if ( ( ! isset($_SESSION['AuthHash']) ) or ( $_SESSION['AuthHashGeneratedAt'] < ( $time - ( ZM_AUTH_HASH_TTL * 1800 ) ) ) ) {
# Don't both regenerating Auth Hash if an hour hasn't gone by yet
$time = localtime();
$local_time = localtime();
$authKey = '';
if ( $useRemoteAddr ) {
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$_SESSION['remoteAddr'].$time[2].$time[3].$time[4].$time[5];
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$_SESSION['remoteAddr'].$local_time[2].$local_time[3].$local_time[4].$local_time[5];
} else {
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$time[2].$time[3].$time[4].$time[5];
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$local_time[2].$local_time[3].$local_time[4].$local_time[5];
}
$auth = md5( $authKey );
if ( session_status() == PHP_SESSION_NONE ) {
@ -167,10 +168,10 @@ function generateAuthHash( $useRemoteAddr ) {
Warning("Session is not active. AuthHash will not be cached. called from $file:$line");
}
$_SESSION['AuthHash'] = $auth;
$_SESSION['AuthHashGeneratedAt'] = time();
$_SESSION['AuthHashGeneratedAt'] = $time;
Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" );
} else {
Logger::Debug( "Using cached auth " . $_SESSION['AuthHash'] );
Logger::Debug( "Using cached auth " . $_SESSION['AuthHash'] ." beacuse " . $_SESSION['AuthHashGeneratedAt'] . ' < '. $time . ' - ' . ZM_AUTH_HASH_TTL . ' * 1800 = '.( $time - (ZM_AUTH_HASH_TTL * 1800) ));
} # end if AuthHash is not cached
return $_SESSION['AuthHash'];
} else {
@ -339,11 +340,11 @@ function getVideoStreamHTML( $id, $src, $width, $height, $format, $title='' ) {
}
function outputImageStream( $id, $src, $width, $height, $title='' ) {
echo getImageStream( $id, $src, $width, $height, $title );
echo getImageStreamHTML( $id, $src, $width, $height, $title );
}
function getImageStream( $id, $src, $width, $height, $title='' ) {
function getImageStreamHTML( $id, $src, $width, $height, $title='' ) {
if ( canStreamIframe() ) {
return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" '.($width? ' width="'. validInt($width).'"' : '').($height?' height="'.validInt($height).'"' : '' ).'/>';
} else {
@ -1239,12 +1240,18 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&amp;' ) {
$value = dbEscape($value);
break;
case 'DateTime':
case 'StartDateTime':
case 'EndDateTime':
$value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'";
break;
case 'Date':
case 'StartDate':
case 'EndDate':
$value = "to_days( '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )";
break;
case 'Time':
case 'StartTime':
case 'EndTime':
$value = "extract( hour_second from '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )";
break;
default :
@ -1281,13 +1288,15 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&amp;' ) {
case 'IS NOT' :
$filter['sql'] .= " IS NOT $value";
break;
default:
Warning("Invalid operator in filter: " . $terms[$i]['op'] );
}
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][op]").'='.urlencode($terms[$i]['op']);
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][op]\" value=\"".htmlspecialchars($terms[$i]['op'])."\"/>\n";
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][val]").'='.urlencode($terms[$i]['val']);
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][val]\" value=\"".htmlspecialchars($terms[$i]['val'])."\"/>\n";
}
} // end foreach term
if ( isset($terms[$i]['cbr']) ) {
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][cbr]").'='.urlencode($terms[$i]['cbr']);
$filter['sql'] .= ' '.str_repeat( ')', $terms[$i]['cbr'] ).' ';
@ -1302,13 +1311,14 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&amp;' ) {
}
}
// Please note that the filter is passed in by copy, so you need to use the return value from this function.
//
function addFilterTerm( $filter, $position, $term=false ) {
if ( $position < 0 )
$position = 0;
if ( ! isset( $filter['Query']['terms'] ) )
$filter['Query']['terms'] = array();
elseif( $position > count($filter['Query']['terms']) )
$position = count($filter['Query']['terms']);
if ( $term && $position == 0 )
@ -1440,6 +1450,66 @@ function getDiskBlocks() {
return( $space );
}
function systemStats() {
$load = getLoad();
$diskPercent = getDiskPercent();
$pathMapPercent = getDiskPercent(ZM_PATH_MAP);
$cpus = getcpus();
$normalized_load = $load / $cpus;
# Colorize the system load stat
if ( $normalized_load <= 0.75 ) {
$htmlLoad=$load;
} elseif ( $normalized_load <= 0.9 ) {
$htmlLoad="<span class=\"warning\">$load</span>";
} elseif ( $normalized_load <= 1.1 ) {
$htmlLoad="<span class=\"error\">$load</span>";
} else {
$htmlLoad="<span class=\"critical\">$load</span>";
}
# Colorize the disk space stat
if ( $diskPercent < 98 ) {
$htmlDiskPercent="$diskPercent%";
} elseif ( $diskPercent <= 99 ) {
$htmlDiskPercent="<span class=\"warning\">$diskPercent%</span>";
} else {
$htmlDiskPercent="<span class=\"error\">$diskPercent%</span>";
}
# Colorize the PATH_MAP (usually /dev/shm) stat
if ( $pathMapPercent < 90 ) {
if ( disk_free_space(ZM_PATH_MAP) > 209715200 ) { # have to always have at least 200MiB free
$htmlPathMapPercent="$pathMapPercent%";
} else {
$htmlPathMapPercent="<span class=\"warning\">$pathMapPercent%</span>";
}
} elseif ( $pathMapPercent < 100 ) {
$htmlPathMapPercent="<span class=\"warning\">$pathMapPercent%</span>";
} else {
$htmlPathMapPercent="<span class=\"critical\">$pathMapPercent%</span>";
}
$htmlString = translate('Load').": $htmlLoad - ".translate('Disk').": $htmlDiskPercent - ".ZM_PATH_MAP.": $htmlPathMapPercent";
return( $htmlString );
}
function getcpus() {
if (is_readable("/proc/cpuinfo") ) { # Works on Linux
preg_match_all('/^processor/m', file_get_contents('/proc/cpuinfo'), $matches);
$num_cpus = count($matches[0]);
} else { # Works on BSD
$matches = explode(":", shell_exec("sysctl hw.ncpu"));
$num_cpus = trim($matches[1]);
}
return( $num_cpus );
}
// Function to fix a problem whereby the built in PHP session handling
// features want to put the sid as a hidden field after the form or
// fieldset tag, neither of which will work with strict XHTML Basic.
@ -2067,7 +2137,7 @@ function cache_bust( $file ) {
# Use the last modified timestamp to create a link that gets a different filename
# To defeat caching. Should probably use md5 hash
$parts = pathinfo($file);
$cacheFile = 'cache/'.$parts['filename'].'-'.filemtime($file).'.'.$parts['extension'];
$cacheFile = 'cache/'.$parts['filename'].'-'.$_COOKIE['zmCSS'].'-'.filemtime($file).'.'.$parts['extension'];
if ( file_exists( ZM_PATH_WEB.'/'.$cacheFile ) or symlink( ZM_PATH_WEB.'/'.$file, ZM_PATH_WEB.'/'.$cacheFile ) ) {
return $cacheFile;
} else {
@ -2141,18 +2211,17 @@ function validHtmlStr( $input ) {
function getStreamHTML( $monitor, $options = array() ) {
if ( isset($options['scale']) and $options['scale'] and ( $options['scale'] != 100 ) ) {
//Warning("Scale to " . $options['scale'] );
$options['width'] = reScale( $monitor->Width(), $options['scale'] );
$options['height'] = reScale( $monitor->Height(), $options['scale'] );
} else {
if ( ! isset( $options['width'] ) ) {
$options['width'] = NULL;
} else if ( $options['width'] == 100 ) {
# scale is empty or 100
# There may be a fixed width applied though, in which case we need to leave the height empty
if ( ! ( isset($options['width']) and $options['width'] ) ) {
$options['width'] = $monitor->Width();
}
if ( ! isset( $options['height'] ) ) {
$options['height'] = NULL;
} else if ( $options['height'] == 100 ) {
$options['height'] = $monitor->Height();
if ( ! ( isset($options['height']) and $options['height'] ) ) {
$options['height'] = $monitor->Height();
}
}
}
if ( ! isset($options['mode'] ) ) {
@ -2161,17 +2230,24 @@ function getStreamHTML( $monitor, $options = array() ) {
$options['maxfps'] = ZM_WEB_VIDEO_MAXFPS;
if ( $monitor->StreamReplayBuffer() )
$options['buffer'] = $monitor->StreamReplayBuffer();
//Warning("width: " . $options['width'] . ' height: ' . $options['height']. ' scale: ' . $options['scale'] );
//FIXME, the width and height of the image need to be scaled.
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
$streamSrc = $monitor->getStreamSrc( array( 'mode'=>'mpeg', 'scale'=>$options['scale'], 'bitrate'=>ZM_WEB_VIDEO_BITRATE, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'format' => ZM_MPEG_LIVE_FORMAT ) );
return getVideoStream( 'liveStream'.$monitor->Id(), $streamSrc, $options, ZM_MPEG_LIVE_FORMAT, $monitor->Name() );
$streamSrc = $monitor->getStreamSrc( array(
'mode'=>'mpeg',
'scale'=>$options['scale'],
'bitrate'=>ZM_WEB_VIDEO_BITRATE,
'maxfps'=>ZM_WEB_VIDEO_MAXFPS,
'format' => ZM_MPEG_LIVE_FORMAT
) );
return getVideoStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], ZM_MPEG_LIVE_FORMAT, $monitor->Name() );
} else if ( $options['mode'] == 'stream' and canStream() ) {
$options['mode'] = 'jpeg';
$streamSrc = $monitor->getStreamSrc( $options );
if ( canStreamNative() )
return getImageStream( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], $monitor->Name());
return getImageStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], $monitor->Name());
elseif ( canStreamApplet() )
// Helper, empty widths and heights really don't work.
return getHelperStream( 'liveStream'.$monitor->Id(), $streamSrc,
@ -2198,6 +2274,7 @@ function getStreamMode( ) {
$streamMode = 'single';
Info( 'The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.' );
}
return $streamMode;
} // end function getStreamMode
function folder_size($dir) {

View File

@ -37,7 +37,7 @@ function loadLanguage( $prefix="" )
$fallbackLangFile = $prefix.'lang/en_gb.php';
$systemLangFile = $prefix.'lang/'.ZM_LANG_DEFAULT.'.php';
if ( isset($user['Language']) )
$userLangFile = $prefix.$user['Language'].'.php';
$userLangFile = $prefix.'lang/'.$user['Language'].'.php';
if ( isset($userLangFile) && file_exists( $userLangFile ) )
return( $userLangFile );

View File

@ -63,16 +63,8 @@ p {
font-weight: normal;
}
th {
font-weight: bold;
color: #016A9d;
}
a:link {
color: #7f7fb2;
text-decoration: none;
}
a:link,
a:visited {
color: #7f7fb2;
text-decoration: none;
@ -83,6 +75,11 @@ a:hover {
text-decoration: underline;
}
th, th a {
font-weight: bold;
color: #016A9d;
}
input,textarea,select,button {
border: 1px #7f7fb2 solid;
font-family: inherit;

View File

@ -12,6 +12,19 @@
float: right;
}
#systemStats .warning {
color: orange;
}
#systemStats .error {
color: red;
}
#systemStats .critical {
color: red;
text-decoration: blink;
}
#monitorSummary {
float: left;
text-align: left;

View File

@ -35,6 +35,7 @@ span.noneCue {
#dataBar #dataTable {
width: 100%;
table-layout: fixed;
}
#dataBar #dataTable td {
@ -142,32 +143,32 @@ span.noneCue {
#monitorStatus #monitorState {
}
.dvrControls {
#dvrControls {
margin-top: 3px;
margin-bottom: 2px;
text-align: center;
}
.dvrControls input {
height: 20px;
width: 28px;
padding-bottom: 3px;
#dvrControls input {
height: 1.5em;
width: 2em;
padding: 0 ;
margin: 0 3px;
}
.dvrControls input[disabled=disabled] {
#dvrControls input[disabled=disabled] {
color: #aaaaaa;
}
.dvrControls input.active {
#dvrControls input.active {
border: 1px solid blue;
}
.dvrControls input.inactive {
#dvrControls input.inactive {
border: 1px solid green;
}
.dvrControls input.unavail {
#dvrControls input.unavail {
border: 1px solid red;
}
@ -194,20 +195,16 @@ span.noneCue {
}
#eventStills {
width: 100%;
position: relative;
}
#eventThumbsPanel {
position: relative;
width: 100%;
margin: 4px auto;
z-index: 1;
}
#eventThumbs {
margin: 0 auto;
width: 100%;
overflow: hidden;
height: 300px;
}
@ -227,13 +224,17 @@ span.noneCue {
#eventImagePanel {
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: 100%;
}
#eventImageFrame {
border: 2px solid gray;
background-color: white;
padding: 4px;
display: inline-block;
}
#eventImage {
@ -243,6 +244,14 @@ span.noneCue {
margin-top: 2px;
}
#eventImageBar::after {
visibility: hidden;
display: block;
content: "";
clear: both;
height: 0;
}
#eventImageStats {
float: left;
}
@ -258,6 +267,7 @@ span.noneCue {
#eventImageNav {
position: relative;
margin: 4px 0 0 0;
}
#eventImageNav input {

View File

@ -1,3 +1,7 @@
.archived {
background-color: #f8f8f8;;
}
#controls {
height: 16px;
width: 100%;

View File

@ -518,7 +518,6 @@ input[type=submit]:disabled {
.sidebar {
position: absolute;
top: 0;
bottom: 0;
left: 0;
z-index: 1000;
display: block;

View File

@ -12,6 +12,19 @@
float: right;
}
#systemStats .warning {
color: orange;
}
#systemStats .error {
color: red;
}
#systemStats .critical {
color: red;
text-decoration: blink;
}
#monitorSummary {
float: left;
text-align: left;

View File

@ -39,6 +39,7 @@ span.noneCue {
#dataBar #dataTable {
width: 100%;
table-layout: fixed;
}
#dataBar #dataTable td {
@ -124,32 +125,32 @@ span.noneCue {
#monitorStatus #monitorState {
}
.dvrControls {
#dvrControls {
margin-top: 3px;
margin-bottom: 2px;
text-align: center;
}
.dvrControls input {
height: 20px;
width: 28px;
padding-bottom: 3px;
#dvrControls input {
height: 1.5em;
width: 2em;
padding: 0;
margin: 0 3px;
}
.dvrControls input[disabled=disabled] {
#dvrControls input[disabled=disabled] {
color: #aaaaaa;
}
.dvrControls input.active {
#dvrControls input.active {
border: 1px solid blue;
}
.dvrControls input.inactive {
#dvrControls input.inactive {
border: 1px solid green;
}
.dvrControls input.unavail {
#dvrControls input.unavail {
border: 1px solid red;
}
@ -176,20 +177,17 @@ span.noneCue {
}
#eventStills {
width: 100%;
position: relative;
}
#eventThumbsPanel {
position: relative;
width: 100%;
margin: 4px auto;
z-index: 1;
}
#eventThumbs {
margin: 0 auto;
width: 100%;
overflow: hidden;
height: 300px;
}
@ -209,13 +207,17 @@ span.noneCue {
#eventImagePanel {
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: 100%;
}
#eventImageFrame {
border: 2px solid gray;
background-color: white;
padding: 4px;
display: inline-block;
}
#eventImage {
@ -225,6 +227,14 @@ span.noneCue {
margin-top: 2px;
}
#eventImageBar::after {
visibility: hidden;
display: block;
content: "";
clear: both;
height: 0;
}
#eventImageStats {
float: left;
}
@ -240,6 +250,7 @@ span.noneCue {
#eventImageNav {
position: relative;
margin: 4px 0 0 0;
}
#eventImageNav input {

View File

@ -1,3 +1,7 @@
.archived {
background-color: #2e2e2e;
}
#controls {
height: 16px;
width: 100%;

View File

@ -250,6 +250,11 @@ ul.tabList li.active a {
font-size: 120%;
}
#content table > tbody > tr:hover
{
background-color: #EEE;
}
.overlay {
font-size: 11px;
}

View File

@ -12,6 +12,19 @@
float: right;
}
#systemStats .warning {
color: orange;
}
#systemStats .error {
color: red;
}
#systemStats .critical {
color: red;
text-decoration: blink;
}
#monitorSummary {
float: left;
text-align: left;

View File

@ -35,6 +35,7 @@ span.noneCue {
#dataBar #dataTable {
width: 100%;
table-layout: fixed;
}
#dataBar #dataTable td {
@ -129,36 +130,36 @@ span.noneCue {
#monitorStatus #monitorState {
}
.dvrControls {
#dvrControls {
margin-top: 3px;
margin-bottom: 2px;
text-align: center;
}
.dvrControls input {
#dvrControls input {
padding: 10px 10px;
width: 50px;
margin: 0 3px;
font-weight: 900;
}
.dvrControls input[disabled=disabled] {
#dvrControls input[disabled=disabled] {
color: #aaaaaa;
}
.dvrControls input.active {
#dvrControls input.active {
border: 0;
background-color: #2ecc71;
color: #fff;
}
.dvrControls input.inactive {
#dvrControls input.inactive {
border: 0;
background-color: #e67e22;
color: #fff;
}
.dvrControls input.unavail {
#dvrControls input.unavail {
background-color: #ccc;
border: 0;
cursor: default;
@ -187,20 +188,17 @@ span.noneCue {
}
#eventStills {
width: 100%;
position: relative;
}
#eventThumbsPanel {
position: relative;
width: 100%;
margin: 4px auto;
margin: 0;
z-index: 1;
}
#eventThumbs {
margin: 0 auto;
width: 100%;
overflow: hidden;
height: 300px;
}
@ -220,13 +218,17 @@ span.noneCue {
#eventImagePanel {
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: 100%;
}
#eventImageFrame {
border: 2px solid gray;
background-color: white;
padding: 4px;
display: inline-block;
}
#eventImage {
@ -249,8 +251,17 @@ span.noneCue {
float: right;
}
#eventImageBar::after {
visibility: hidden;
display: block;
content: "";
clear: both;
height: 0;
}
#eventImageNav {
position: relative;
margin: 4px 0 0 0;
}
#eventImageNav input {

View File

@ -1,3 +1,7 @@
.archived {
background-color: #f8f8f8;;
}
#controls {
height: 16px;
width: 100%;

View File

@ -25,6 +25,7 @@
var popupOptions = "resizable,scrollbars,status=no,toolbar=yes";
function checkSize() {
if ( 0 ) {
if (window.outerHeight) {
var w = window.outerWidth;
var prevW = w;
@ -37,6 +38,7 @@ function checkSize() {
if (w != prevW || h != prevH)
window.resizeTo(w, h);
}
}
}
// Deprecated
@ -324,7 +326,7 @@ function changeGroup( e, depth ) {
}
function changeMonitor( e ) {
var monitor_id = e.value;
Cookie.write( 'zmMonitorId', monitor_id, { duration: 10*365 } );
Cookie.write( 'MonitorId', monitor_id, { duration: 10*365 } );
window.location = window.location;
}
function changeFilter( e ) {

View File

@ -59,7 +59,7 @@ if ( ( ! empty($closePopup) ) and ( $closePopup == true ) ) {
var focusWindow = <?php echo !empty($focusWindow)?'true':'false' ?>;
var imagePrefix = "<?php echo viewImagePath( "", '&' ) ?>";
var imagePrefix = "<?php echo "?view=image&eid=" ?>";
var auth_hash;
<?php if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS ) { ?>

Some files were not shown because too many files have changed in this diff Show More