diff --git a/.travis.yml b/.travis.yml index 08e086955..916cd5a98 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/README.md b/README.md index 4c318b659..1d43ff560 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index a4802ef98..91089ff2d 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -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 */; diff --git a/db/zm_update-1.31.11.sql b/db/zm_update-1.31.11.sql index de17d85d9..e0772cef4 100644 --- a/db/zm_update-1.31.11.sql +++ b/db/zm_update-1.31.11.sql @@ -67,3 +67,4 @@ SET @s = (SELECT IF( PREPARE stmt FROM @s; EXECUTE stmt; + diff --git a/db/zm_update-1.31.13.sql b/db/zm_update-1.31.13.sql new file mode 100644 index 000000000..dd63b347a --- /dev/null +++ b/db/zm_update-1.31.13.sql @@ -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; diff --git a/db/zm_update-1.31.2.sql b/db/zm_update-1.31.2.sql index c94e3302a..9761987d1 100644 --- a/db/zm_update-1.31.2.sql +++ b/db/zm_update-1.31.2.sql @@ -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); + diff --git a/distros/ubuntu1604/rules b/distros/ubuntu1604/rules index 5cf153266..53a9a237a 100755 --- a/distros/ubuntu1604/rules +++ b/distros/ubuntu1604/rules @@ -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) diff --git a/distros/ubuntu1604/zoneminder.postinst b/distros/ubuntu1604/zoneminder.postinst index e06cdd3b5..dedbf7096 100644 --- a/distros/ubuntu1604/zoneminder.postinst +++ b/distros/ubuntu1604/zoneminder.postinst @@ -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... diff --git a/docs/installationguide/ubuntu.rst b/docs/installationguide/ubuntu.rst index e561e7477..fe95754d1 100644 --- a/docs/installationguide/ubuntu.rst +++ b/docs/installationguide/ubuntu.rst @@ -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 :: diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in index d2b444ef4..f69e95b18 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -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() ) { diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Floureon.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Floureon.pm new file mode 100644 index 000000000..bb3504067 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Floureon.pm @@ -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, Eogibankov@gmail.comE + +=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 + diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index 2fc590977..8c4eba093 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -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} ) { diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index cbb68faff..1593777b4 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -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 diff --git a/scripts/zmpkg.pl.in b/scripts/zmpkg.pl.in index 597d7ac1a..bc57430f4 100644 --- a/scripts/zmpkg.pl.in +++ b/scripts/zmpkg.pl.in @@ -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 diff --git a/scripts/zmwatch.pl.in b/scripts/zmwatch.pl.in index 393d8fe90..c1a2d78e7 100644 --- a/scripts/zmwatch.pl.in +++ b/scripts/zmwatch.pl.in @@ -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) diff --git a/src/snprintf.cpp b/src/snprintf.cpp deleted file mode 100644 index 3476822de..000000000 --- a/src/snprintf.cpp +++ /dev/null @@ -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; - } - } - } - diff --git a/src/zm_box.h b/src/zm_box.h index 3432bacc5..fa377e593 100644 --- a/src/zm_box.h +++ b/src/zm_box.h @@ -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 ) ) { } diff --git a/src/zm_buffer.h b/src/zm_buffer.h index 31898eb95..8f47c7cbc 100644 --- a/src/zm_buffer.h +++ b/src/zm_buffer.h @@ -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; } diff --git a/src/zm_camera.cpp b/src/zm_camera.cpp index 0ea7af373..afcce7616 100644 --- a/src/zm_camera.cpp +++ b/src/zm_camera.cpp @@ -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() { diff --git a/src/zm_comms.cpp b/src/zm_comms.cpp index 24d1a1a63..228e02f37 100644 --- a/src/zm_comms.cpp +++ b/src/zm_comms.cpp @@ -42,11 +42,10 @@ #include // 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 ); } diff --git a/src/zm_comms.h b/src/zm_comms.h index ae5fd5b08..b5974771d 100644 --- a/src/zm_comms.h +++ b/src/zm_comms.h @@ -37,26 +37,20 @@ #include #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 CommsSet; typedef std::vector CommsList; diff --git a/src/zm_config.cpp b/src/zm_config.cpp index 9ab484fb4..116ccc274 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -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; diff --git a/src/zm_config.h.in b/src/zm_config.h.in index a62057f1c..d09a2f351 100644 --- a/src/zm_config.h.in +++ b/src/zm_config.h.in @@ -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(); } }; diff --git a/src/zm_coord.h b/src/zm_coord.h index 5858cef23..9bf31144c 100644 --- a/src/zm_coord.h +++ b/src/zm_coord.h @@ -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 ); } diff --git a/src/zm_curl_camera.cpp b/src/zm_curl_camera.cpp index dbd824dad..9277307a8 100644 --- a/src/zm_curl_camera.cpp +++ b/src/zm_curl_camera.cpp @@ -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(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(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(userdata)->progress_callback(userdata,dltotal,dlnow,ultotal,ulnow); } void* thread_func_dispatcher(void* object) { - return ((cURLCamera*)object)->thread_func(); + return reinterpret_cast(object)->thread_func(); } #endif // HAVE_LIBCURL diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 9b98ea4c1..57ebafbd0 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -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 ¬es ) { 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 ¬eSet = 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) ); diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index fc85ad0de..817c8753a 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -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 ) { diff --git a/src/zm_eventstream.h b/src/zm_eventstream.h index 07e161214..c5964ee0b 100644 --- a/src/zm_eventstream.h +++ b/src/zm_eventstream.h @@ -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; diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index 4ba88d900..ce0cd0eff 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -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; diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index ee5437633..7a7a5f157 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -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? diff --git a/src/zm_ffmpeg_camera.h b/src/zm_ffmpeg_camera.h index 9e10b76bf..9f83d8a15 100644 --- a/src/zm_ffmpeg_camera.h +++ b/src/zm_ffmpeg_camera.h @@ -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; diff --git a/src/zm_ffmpeg_input.cpp b/src/zm_ffmpeg_input.cpp index 6c715b6d1..70dafb76c 100644 --- a/src/zm_ffmpeg_input.cpp +++ b/src/zm_ffmpeg_input.cpp @@ -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 ); diff --git a/src/zm_ffmpeg_input.h b/src/zm_ffmpeg_input.h index 3e12f45cc..727fc110a 100644 --- a/src/zm_ffmpeg_input.h +++ b/src/zm_ffmpeg_input.h @@ -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; diff --git a/src/zm_image.cpp b/src/zm_image.cpp index 9dfb447da..1c0e5ac41 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -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; diff --git a/src/zm_image.h b/src/zm_image.h index 934d2a682..104ccdcdc 100644 --- a/src/zm_image.h +++ b/src/zm_image.h @@ -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(p1), *e2 = reinterpret_cast(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(p1), *e2 = reinterpret_cast(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(); diff --git a/src/zm_jpeg.cpp b/src/zm_jpeg.cpp index ba0085c6b..cddf086c5 100644 --- a/src/zm_jpeg.cpp +++ b/src/zm_jpeg.cpp @@ -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); diff --git a/src/zm_libvlc_camera.cpp b/src/zm_libvlc_camera.cpp index 70d833c31..9779fb024 100644 --- a/src/zm_libvlc_camera.cpp +++ b/src/zm_libvlc_camera.cpp @@ -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(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(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) { diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index e6bc1a405..76f79fd58 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -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 ) { diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index d01e269c9..9c8efd456 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -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() ); diff --git a/src/zm_mem_utils.h b/src/zm_mem_utils.h index dd0e2a3f9..50809016c 100644 --- a/src/zm_mem_utils.h +++ b/src/zm_mem_utils.h @@ -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 ); } } diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 7e0d4b630..4933bd0fc 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -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 diff --git a/src/zm_monitor.h b/src/zm_monitor.h index 925e0d14a..780c10b7c 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -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 ); diff --git a/src/zm_monitorstream.cpp b/src/zm_monitorstream.cpp index 010877b90..ed8009f84 100644 --- a/src/zm_monitorstream.cpp +++ b/src/zm_monitorstream.cpp @@ -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; diff --git a/src/zm_monitorstream.h b/src/zm_monitorstream.h index fb8e22a13..3e2dfbb1f 100644 --- a/src/zm_monitorstream.h +++ b/src/zm_monitorstream.h @@ -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 ) { diff --git a/src/zm_mpeg.cpp b/src/zm_mpeg.cpp index e949052dc..0280c7f23 100644 --- a/src/zm_mpeg.cpp +++ b/src/zm_mpeg.cpp @@ -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(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); diff --git a/src/zm_mpeg.h b/src/zm_mpeg.h index 931f9d687..fbc3eed4d 100644 --- a/src/zm_mpeg.h +++ b/src/zm_mpeg.h @@ -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; diff --git a/src/zm_packet.cpp b/src/zm_packet.cpp index 7c08d4158..a04282d26 100644 --- a/src/zm_packet.cpp +++ b/src/zm_packet.cpp @@ -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"); diff --git a/src/zm_packet.h b/src/zm_packet.h index 1758b0106..bdb67cb57 100644 --- a/src/zm_packet.h +++ b/src/zm_packet.h @@ -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(); }; diff --git a/src/zm_poly.h b/src/zm_poly.h index 41d7b7c64..0fcf34a6e 100644 --- a/src/zm_poly.h +++ b/src/zm_poly.h @@ -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(p1), *e2 = reinterpret_cast(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(p1), *e2 = reinterpret_cast(p2); return( int(e1->min_x - e2->min_x) ); } }; diff --git a/src/zm_remote_camera.cpp b/src/zm_remote_camera.cpp index 6afc7251b..0acd4e709 100644 --- a/src/zm_remote_camera.cpp +++ b/src/zm_remote_camera.cpp @@ -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; diff --git a/src/zm_remote_camera.h b/src/zm_remote_camera.h index a0d391d9b..32e22c47a 100644 --- a/src/zm_remote_camera.h +++ b/src/zm_remote_camera.h @@ -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; diff --git a/src/zm_remote_camera_http.cpp b/src/zm_remote_camera_http.cpp index 2907e90a3..f1f3ec427 100644 --- a/src/zm_remote_camera_http.cpp +++ b/src/zm_remote_camera_http.cpp @@ -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:"; diff --git a/src/zm_remote_camera_nvsocket.cpp b/src/zm_remote_camera_nvsocket.cpp index 78f65bd92..98eff70cd 100644 --- a/src/zm_remote_camera_nvsocket.cpp +++ b/src/zm_remote_camera_nvsocket.cpp @@ -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 ); } diff --git a/src/zm_remote_camera_nvsocket.h b/src/zm_remote_camera_nvsocket.h index 4f62bafe3..67df93032 100644 --- a/src/zm_remote_camera_nvsocket.h +++ b/src/zm_remote_camera_nvsocket.h @@ -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);}; diff --git a/src/zm_rtp_ctrl.cpp b/src/zm_rtp_ctrl.cpp index 3973e5a71..b586c979f 100644 --- a/src/zm_rtp_ctrl.cpp +++ b/src/zm_rtp_ctrl.cpp @@ -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(*iter) ) { diff --git a/src/zm_rtp_data.cpp b/src/zm_rtp_data.cpp index 496c0bcfd..4fbf0cd04 100644 --- a/src/zm_rtp_data.cpp +++ b/src/zm_rtp_data.cpp @@ -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(*iter) ) { diff --git a/src/zm_rtsp.cpp b/src/zm_rtsp.cpp index f84b2aa53..897859435 100644 --- a/src/zm_rtsp.cpp +++ b/src/zm_rtsp.cpp @@ -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 ); diff --git a/src/zm_rtsp.h b/src/zm_rtsp.h index 51a2c99aa..14ef02010 100644 --- a/src/zm_rtsp.h +++ b/src/zm_rtsp.h @@ -31,8 +31,7 @@ #include #include -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; diff --git a/src/zm_rtsp_auth.cpp b/src/zm_rtsp_auth.cpp index 6598bd254..9b91ff65c 100644 --- a/src/zm_rtsp_auth.cpp +++ b/src/zm_rtsp_auth.cpp @@ -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) { diff --git a/src/zm_rtsp_auth.h b/src/zm_rtsp_auth.h index 152dab85a..34056eee6 100644 --- a/src/zm_rtsp_auth.h +++ b/src/zm_rtsp_auth.h @@ -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; }; diff --git a/src/zm_sdp.cpp b/src/zm_sdp.cpp index ffcea791b..1361c5143 100644 --- a/src/zm_sdp.cpp +++ b/src/zm_sdp.cpp @@ -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); diff --git a/src/zm_sdp.h b/src/zm_sdp.h index 48a05b706..ae7cd67a2 100644 --- a/src/zm_sdp.h +++ b/src/zm_sdp.h @@ -31,13 +31,11 @@ #include #include -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; } }; diff --git a/src/zm_storage.h b/src/zm_storage.h index e47986801..75817a903 100644 --- a/src/zm_storage.h +++ b/src/zm_storage.h @@ -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 ); } diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index 282db0f40..8c488194b 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -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); } } } - diff --git a/src/zm_stream.h b/src/zm_stream.h index dbe4c1db6..5623f8a0d 100644 --- a/src/zm_stream.h +++ b/src/zm_stream.h @@ -141,6 +141,8 @@ public: #if HAVE_LIBAVCODEC vid_stream = 0; #endif // HAVE_LIBAVCODEC + last_frame_sent = 0.0; + msg = { 0, { 0 } }; } virtual ~StreamBase(); diff --git a/src/zm_thread.h b/src/zm_thread.h index 8c84d9041..771d6e80b 100644 --- a/src/zm_thread.h +++ b/src/zm_thread.h @@ -32,8 +32,7 @@ #include #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 ThreadData -{ +template 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() {} diff --git a/src/zm_user.cpp b/src/zm_user.cpp index 58de254bd..b6c9f9553 100644 --- a/src/zm_user.cpp +++ b/src/zm_user.cpp @@ -27,11 +27,12 @@ #include #include +#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::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 { diff --git a/src/zm_user.h b/src/zm_user.h index 648ef21db..725acbfa2 100644 --- a/src/zm_user.h +++ b/src/zm_user.h @@ -36,8 +36,8 @@ #include #endif // HAVE_L || HAVE_LIBCRYPTO -class User -{ +#include +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 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 ); } diff --git a/src/zm_utils.cpp b/src/zm_utils.cpp index f6ce68089..9ba8cc420 100644 --- a/src/zm_utils.cpp +++ b/src/zm_utils.cpp @@ -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& 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); diff --git a/src/zm_utils.h b/src/zm_utils.h index 961389611..a10c89f48 100644 --- a/src/zm_utils.h +++ b/src/zm_utils.h @@ -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 ); diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index c8704eae0..e6c4769b1 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -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 diff --git a/src/zm_zone.cpp b/src/zm_zone.cpp index 2bfdb404b..d84af6036 100644 --- a/src/zm_zone.cpp +++ b/src/zm_zone.cpp @@ -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) ) { diff --git a/src/zmc.cpp b/src/zmc.cpp index 7c0995621..bafd4faf6 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -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(); diff --git a/src/zmf.cpp b/src/zmf.cpp deleted file mode 100644 index fac1b76c8..000000000 --- a/src/zmf.cpp +++ /dev/null @@ -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 - zmf --monitor - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 \n" ); - fprintf( stderr, "Options:\n" ); - fprintf( stderr, " -m, --monitor : 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(); -} diff --git a/src/zms.cpp b/src/zms.cpp index d8fc0a86c..b78b20c66 100644 --- a/src/zms.cpp +++ b/src/zms.cpp @@ -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" ); diff --git a/src/zmu.cpp b/src/zmu.cpp index 7333e477e..46ba35ac6 100644 --- a/src/zmu.cpp +++ b/src/zmu.cpp @@ -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++ ) { diff --git a/utils/do_debian_package.sh b/utils/do_debian_package.sh index 5034f0fb9..d2408da14 100755 --- a/utils/do_debian_package.sh +++ b/utils/do_debian_package.sh @@ -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 diff --git a/utils/generate_apache_config.pl b/utils/generate_apache_config.pl index 7fac19bc3..9d9e94e10 100755 --- a/utils/generate_apache_config.pl +++ b/utils/generate_apache_config.pl @@ -37,6 +37,8 @@ if ( $$opts{protocol} eq 'https' ) { die "https requires a server_name"; } $VirtualHostPorts = ' *:443'; +} else { + $VirtualHostPorts = ' *:80'; } diff --git a/web/ajax/status.php b/web/ajax/status.php index 6827b7e79..3941a5645 100644 --- a/web/ajax/status.php +++ b/web/ajax/status.php @@ -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', diff --git a/web/api/app/Controller/EventsController.php b/web/api/app/Controller/EventsController.php index f3e054c42..b5a17d461 100644 --- a/web/api/app/Controller/EventsController.php +++ b/web/api/app/Controller/EventsController.php @@ -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')); diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index a0a4c8c6b..9ad487917 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -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; diff --git a/web/includes/Event.php b/web/includes/Event.php index 392973a6a..0c9a15b87 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -9,6 +9,7 @@ class Event { 'StorageId', 'Name', 'DiskSpace', +'SaveJPEGs', ); public function __construct( $IdOrRow = null ) { $row = NULL; diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index e7b114dde..edc946c0c 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -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='&' ) { + + $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'}); diff --git a/web/includes/database.php b/web/includes/database.php index 34387e040..a1bcf66c3 100644 --- a/web/includes/database.php +++ b/web/includes/database.php @@ -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 ); } diff --git a/web/includes/functions.php b/web/includes/functions.php index 8dcab3b42..7bd3df7e9 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -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 '