Merge branch 'ZoneMinder:master' into master

pull/3835/head
BHMSD-bdailey 2024-02-21 10:48:24 -05:00 committed by GitHub
commit ec24235cd3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 261 additions and 244 deletions

View File

@ -1,7 +1,7 @@
# ==========================================================================
#
# ZoneMinder Server Module, $Date$, $Revision$
# Copyright (C) 2001-2008 Philip Coombes
# ZoneMinder Server Module
# Copyright (C) 2023 ZoneMinder Inc
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -19,94 +19,52 @@
#
# ==========================================================================
#
# This module contains the common definitions and functions used by the rest
# of the ZoneMinder scripts
#
package ZoneMinder::Server;
use 5.006;
use strict;
use warnings;
require Exporter;
require ZoneMinder::Base;
require ZoneMinder::Config;
require ZoneMinder::Logger;
require ZoneMinder::Object;
our @ISA = qw(Exporter ZoneMinder::Base);
use parent qw(ZoneMinder::Object);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
# This allows declaration use ZoneMinder ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
our %EXPORT_TAGS = (
'functions' => [ qw(
CpuLoad
) ]
);
push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS;
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
our $VERSION = $ZoneMinder::Base::VERSION;
# ==========================================================================
#
# General Utility Functions
#
# ==========================================================================
use ZoneMinder::Config qw(:all);
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Database qw(:all);
use POSIX;
sub new {
my ( $parent, $id, $data ) = @_;
my $self = {};
bless $self, $parent;
if ( ( $$self{Id} = $id ) or $data ) {
#$log->debug("loading $parent $id") if $debug or DEBUG_ALL;
$self->load( $data );
}
return $self;
} # end sub new
sub load {
my ( $self, $data ) = @_;
my $type = ref $self;
if ( ! $data ) {
#$log->debug("Object::load Loading from db $type");
$data = $ZoneMinder::Database::dbh->selectrow_hashref( 'SELECT * FROM Servers WHERE Id=?', {}, $$self{Id} );
if ( ! $data ) {
if ( $ZoneMinder::Database::dbh->errstr ) {
Error( "Failure to load Server record for $$self{id}: Reason: " . $ZoneMinder::Database::dbh->errstr );
} # end if
} # end if
} # end if ! $data
if ( $data and %$data ) {
@$self{keys %$data} = values %$data;
} # end if
} # end sub load
sub Name {
if ( @_ > 1 ) {
$_[0]{Name} = $_[1];
}
return $_[0]{Name};
} # end sub Name
sub Hostname {
if ( @_ > 1 ) {
$_[0]{Hostname} = $_[1];
}
return $_[0]{Hostname};
} # end sub Hostname
use vars qw/ $table $primary_key %fields $serial @identified_by %defaults $debug/;
$debug = 0;
$table = 'Servers';
@identified_by = ('Id');
$serial = $primary_key = 'Id';
%fields = map { $_, $_ } qw(
Id
Name
Protocol
Hostname
Port
PathToIndex
PathToZMS
PathToApi
State_Id
Status
CpuLoad
CpuUserPercent
CpuNicePercent
CpuSystemPercent
CpuIdlePercent
CpuUsagePercent
TotalMem
FreeMem
TotalSwap
FreeSwap
zmstats
zmaudit
zmtrigger
zmeventnotification
Latitude
Longitude
);
sub CpuLoad {
my $output = qx(uptime);
@ -114,16 +72,84 @@ sub CpuLoad {
# returned value is 1min, 5min, 15min load
if (join(', ',@sysloads) =~ /(\d+\.\d+)\s*,\s+(\d+\.\d+)\s*,\s+(\d+\.\d+)\s*$/) {
if (@_) {
my $self = shift;
$$self{CpuLoad} = $sysloads[0];
}
return @sysloads;
}
return (undef, undef, undef);
} # end sub CpuLoad
sub CpuUsage {
if (-e '/proc/stat') {
if (!open(STAT, '/proc/stat')) {
Error("Enable to open /proc/stat: $!");
return;
}
my ($self, $prev_user, $prev_nice, $prev_sys, $prev_idle, $prev_total);
if (@_==1) {
$self = shift;
($prev_user, $prev_nice, $prev_sys, $prev_idle, $prev_total) = @$self{'prev_user','prev_nice','prev_sys','prev_idle','prev_total'};
} elsif (@_>1) {
$self = {};
($prev_user, $prev_nice, $prev_sys, $prev_idle, $prev_total) = @_;
}
my ($cpu_user, $cpu_nice, $cpu_sys, $cpu_idle);
while (<STAT>) {
if (/^cpu\s+[0-9]+/) {
(undef, $cpu_user, $cpu_nice, $cpu_sys, $cpu_idle) = split /\s+/, $_;
last;
}
}
close STAT;
my $total = $cpu_user + $cpu_nice + $cpu_sys + $cpu_idle;
my $diff_user = $prev_user ? $cpu_user - $prev_user : $cpu_user;
my $diff_nice = $prev_nice ? $cpu_nice - $prev_nice : $cpu_nice;
my $diff_sys = $prev_sys ? $cpu_sys - $prev_sys : $cpu_sys;
my $diff_idle = $prev_idle ? $cpu_idle - $prev_idle : $cpu_idle;
my $diff_total = $prev_total ? $total - $prev_total : $total;
my $user_percent = 100 * $diff_user / $diff_total;
my $nice_percent = 100 * $diff_nice / $diff_total;
my $sys_percent = 100 * $diff_sys / $diff_total;
my $idle_percent = 100 * $diff_idle / $diff_total;
my $usage_percent = 100 * ($diff_total - $diff_idle) / $diff_total;
$$self{prev_user} = $cpu_user;
$$self{prev_nice} = $cpu_nice;
$$self{prev_sys} = $cpu_sys;
$$self{prev_idle} = $cpu_sys;
$$self{prev_total} = $cpu_sys;
return ($user_percent, $nice_percent, $sys_percent, $idle_percent, $usage_percent);
} else {
# Get CPU utilization percentages
my $top_output = `top -b -n 1 | grep -i "^%Cpu(s)" | awk '{print \$2, \$4, \$6, \$8}'`;
my ($user, $system, $nice, $idle) = split(/ /, $top_output);
$user =~ s/[^\d\.]//g;
$system =~ s/[^\d\.]//g;
$nice =~ s/[^\d\.]//g;
$idle =~ s/[^\d\.]//g;
if (!$user) {
Warning("Failed getting user_utilization from $top_output");
$user = 0;
}
if (!$system) {
Warning("Failed getting user_utilization from $top_output");
$system = 0;
}
return ($user, $nice, $system, $idle, $user + $system);
}
} # end sub CpuUsage
sub PathToZMS {
my $this = shift;
$this->{PathToZMS} = shift if @_;
if ( $this->Id() and $this->{PathToZMS} ) {
if ($this->Id() and $this->{PathToZMS}) {
return $this->{PathToZMS};
} else {
return $ZoneMinder::Config{ZM_PATH_ZMS};
@ -182,53 +208,13 @@ sub PathToApi {
1;
__END__
# Below is stub documentation for your module. You'd better edit it!
=head1 NAME
ZoneMinder::Database - Perl extension for blah blah blah
ZoneMinder::Server - Perl extension for the ZoneMinder Server Object
=head1 SYNOPSIS
use ZoneMinder::Server;
blah blah blah
=head1 DESCRIPTION
Stub documentation for ZoneMinder, created by h2xs. It looks like the
author of the extension was negligent enough to leave the stub
unedited.
Blah blah blah.
=head2 EXPORT
None by default.
=head1 SEE ALSO
Mention other useful documentation such as the documentation of
related modules or operating system documentation (such as man pages
in UNIX), or any relevant external documentation such as RFCs or
standards.
If you have a mailing list set up for your module, mention it here.
If you have a web site set up for your module, mention it here.
=head1 AUTHOR
Philip Coombes, E<lt>philip.coombes@zoneminder.comE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2001-2008 Philip Coombes
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.3 or,
at your option, any later version of Perl 5 you may have available.
=cut

View File

@ -65,6 +65,7 @@ use constant MAX_CONNECT_DELAY => 40;
@EXTRA_PERL_LIB@
use ZoneMinder;
use ZoneMinder::Server;
use POSIX;
use Socket;
use IO::Handle;
@ -155,12 +156,15 @@ socket(CLIENT, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!");
my $saddr = sockaddr_un(SOCK_FILE);
my $server_up = connect(CLIENT, $saddr);
if ( !$server_up ) {
if ( $Config{ZM_SERVER_ID} ) {
if (!$server_up) {
my $server = new ZoneMinder::Server($Config{ZM_SERVER_ID});
if ($server->Id()) {
use Sys::MemInfo qw(totalmem freemem totalswap freeswap);
use ZoneMinder::Server qw(CpuLoad);
if ( ! defined $dbh->do(q{UPDATE Servers SET Status=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?}, undef,
'NotRunning', &totalmem, &freemem, &totalswap, &freeswap, $Config{ZM_SERVER_ID} ) ) {
my ($user_percent, $nice_percent, $sys_percent, $idle_percent, $usage_percent) = $server->CpuUsage();
if ($_=$server->save({Status=>'NotRunning',
TotalMem=>&totalmem, FreeMem=>&freemem, TotalSwap=>&totalswap, FreeSwap=>&freeswap,
CpuUserPercent=>$user_percent, CpuNicePercent=>$nice_percent, CpuSysPercent=>$sys_percent, CpuIdlePercent=>$idle_percent, CpuUsagePercent=>$usage_percent,
})) {
Error('Failed Updating status of Server record to Not Running for Id='.$Config{ZM_SERVER_ID}.': '.$dbh->errstr());
}
}
@ -237,7 +241,7 @@ use Socket;
use IO::Handle;
use Time::HiRes qw(usleep);
use Sys::MemInfo qw(totalmem freemem totalswap freeswap);
use ZoneMinder::Server qw(CpuLoad);
use ZoneMinder::Server;
#use Data::Dumper;
use constant KILL_DELAY => 30; # seconds to wait between sending TERM and sending KILL
@ -304,9 +308,11 @@ sub run {
my $timeout = 1;
my $secs_count = 0;
my $server = new ZoneMinder::Server($Config{ZM_SERVER_ID});
while ( !$zm_terminate ) {
if ( $Config{ZM_SERVER_ID} ) {
if ($server->Id()) {
if ( ! ( $secs_count % 60 ) ) {
while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) {
Warning("Not connected to db ($dbh)".($dbh?' ping('.$dbh->ping().')':''). ($DBI::errstr?" errstr($DBI::errstr)":'').' Reconnecting');
@ -315,11 +321,13 @@ sub run {
}
last if $zm_terminate;
my @cpuload = CpuLoad();
Debug("Updating Server record @cpuload");
if ( ! defined $dbh->do('UPDATE Servers SET Status=?,CpuLoad=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?', undef,
'Running', $cpuload[0], &totalmem, &freemem, &totalswap, &freeswap, $Config{ZM_SERVER_ID} ) ) {
Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID} :".$dbh->errstr());
my @cpuload = ZoneMinder::Server::CpuLoad();
my ($user_percent, $nice_percent, $sys_percent, $idle_percent, $usage_percent) = $server->CpuUsage();
if ($_=$server->save({Status=>'Running',
TotalMem=>&totalmem, FreeMem=>&freemem, TotalSwap=>&totalswap, FreeSwap=>&freeswap, CpuLoad=>$cpuload[0],
CpuUserPercent=>$user_percent, CpuNicePercent=>$nice_percent, CpuSysPercent=>$sys_percent, CpuIdlePercent=>$idle_percent, CpuUsagePercent=>$usage_percent
})) {
Error('Failed Updating status of Server record to Not Running for Id='.$Config{ZM_SERVER_ID}.': '.$dbh->errstr());
}
}
$secs_count += 1;
@ -384,14 +392,12 @@ sub run {
reaper() if %pids_to_reap;
} # end while
dPrint(ZoneMinder::Logger::INFO, 'Server exiting at '
.strftime('%y/%m/%d %H:%M:%S', localtime())
."\n"
);
if ( $Config{ZM_SERVER_ID} ) {
dPrint(ZoneMinder::Logger::INFO, 'Server exiting at '.strftime('%y/%m/%d %H:%M:%S', localtime())."\n");
if ($Config{ZM_SERVER_ID}) {
$dbh = zmDbConnect() if ! ($dbh and $dbh->ping());
if ( ! defined $dbh->do(q{UPDATE Servers SET Status='NotRunning' WHERE Id=?}, undef, $Config{ZM_SERVER_ID}) ) {
Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID}".$dbh->errstr());
my $server = new ZoneMinder::Server($Config{ZM_SERVER_ID});
if ($_=$server->save({Status=>'NotRunning'})) {
Error('Failed Updating status of Server record to Not Running for Id='.$Config{ZM_SERVER_ID}.': '.$dbh->errstr());
}
}
shutdownAll();

View File

@ -21,7 +21,7 @@ use constant START_DELAY => 30; # To give everything else time to start
use ZoneMinder;
use DBI;
use Sys::MemInfo qw(totalmem freemem totalswap freeswap);
use ZoneMinder::Server qw(CpuLoad);
use ZoneMinder::Server;
$| = 1;
@ -43,6 +43,7 @@ Info('Stats Daemon starting in '.START_DELAY.' seconds');
sleep(START_DELAY);
my $dbh = zmDbConnect();
my $server = new ZoneMinder::Server($Config{ZM_SERVER_ID});
while (!$zm_terminate) {
while ( ! ( $dbh and $dbh->ping() ) ) {
@ -53,34 +54,18 @@ while (!$zm_terminate) {
}
}
my @cpuload = CpuLoad();
if ( $Config{ZM_SERVER_ID} and ! defined $dbh->do('UPDATE Servers SET Status=?,CpuLoad=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?', undef,
'Running', $cpuload[0], &totalmem, &freemem, &totalswap, &freeswap, $Config{ZM_SERVER_ID} ) ) {
Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID} :".$dbh->errstr());
}
# Get CPU utilization percentages
my $top_output = `top -b -n 1 | grep -i "^%Cpu(s)" | awk '{print \$2, \$4}'`;
my ($user_utilization, $system_utilization) = split(/ /, $top_output);
$user_utilization =~ s/[^\d\.]//g;
$system_utilization =~ s/[^\d\.]//g;
if (!$user_utilization) {
Warning("Failed getting user_utilization from $top_output");
$user_utilization = 0;
}
if (!$system_utilization) {
Warning("Failed getting user_utilization from $top_output");
$system_utilization = 0;
}
my @cpuload = $server->CpuLoad();
my ($user_percent, $nice_percent, $sys_percent, $idle_percent, $usage_percent) = $server->CpuUsage();
zmDbDo('INSERT INTO Server_Stats (ServerId, TimeStamp, CpuLoad, CpuUserPercent, CpuSystemPercent, TotalMem, FreeMem, TotalSwap, FreeSwap) VALUES (?,NOW(),?,?,?,?,?,?,?)',
$Config{ZM_SERVER_ID},
$cpuload[0], $user_utilization, $system_utilization,
$cpuload[0], $user_percent, $sys_percent,
&totalmem, &freemem, &totalswap, &freeswap);
my $rows = zmDbDo('DELETE FROM `Server_Stats` WHERE `TimeStamp` < now() - interval 1 DAY LIMIT 100');
Debug("Deleted $rows Server Stats table entries by time");
{
my $rows = zmDbDo('DELETE FROM `Server_Stats` WHERE `TimeStamp` < now() - interval 1 DAY LIMIT 100');
Debug("Deleted $rows Server Stats table entries by time");
}
# Clear out statuses for Monitors that have been set to None but for some reason didn't update the db
zmDbDo('DELETE FROM Monitor_Status WHERE MonitorId IN (SELECT Id FROM Monitors WHERE Capturing=\'None\')');
@ -114,18 +99,20 @@ while (!$zm_terminate) {
}
my $rows;
do {
$rows = zmDbDo('DELETE FROM `Logs` WHERE `TimeKey` < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.') LIMIT 100');
$rows = zmDbDo('DELETE low_priority FROM `Logs` WHERE `TimeKey` < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.') LIMIT 100');
Debug("Deleted $rows log table entries by time") if $rows;
} while ($rows and ($rows == 100) and !$zm_terminate);
}
} # end if ZM_LOG_DATABASE_LIMIT
my $rows;
do {
# Delete any sessions that are more than a week old. Limiting to 100 because mysql sucks
$rows = zmDbDo('DELETE FROM Sessions WHERE access < ? LIMIT 100', time - $Config{ZM_COOKIE_LIFETIME});
Debug("Deleted $rows sessions") if $rows;
} while ($rows and ($rows == 100) and !$zm_terminate);
{
my $rows;
do {
# Delete any sessions that are more than a week old. Limiting to 100 because mysql sucks
$rows = zmDbDo('DELETE FROM Sessions WHERE access < ? LIMIT 100', time - $Config{ZM_COOKIE_LIFETIME});
Debug("Deleted $rows sessions") if $rows;
} while ($rows and ($rows == 100) and !$zm_terminate);
}
sleep($Config{ZM_STATS_UPDATE_INTERVAL});
} # end while (!$zm_terminate)

View File

@ -21,6 +21,7 @@
#include "zm_logger.h"
#include "zm_signal.h"
#include <cstdlib>
#include <unistd.h>
MYSQL dbconn;
std::mutex db_mutex;
@ -32,12 +33,12 @@ bool zmDbConnected = false;
bool zmDbConnect() {
// For some reason having these lines causes memory corruption and crashing on newer debian/ubuntu
// But they really need to be here in order to prevent a double open of mysql
if ( zmDbConnected ) {
if (zmDbConnected) {
//Warning("Calling zmDbConnect when already connected");
return true;
}
if ( !mysql_init(&dbconn) ) {
if (!mysql_init(&dbconn)) {
Error("Can't initialise database connection: %s", mysql_error(&dbconn));
return false;
}
@ -94,7 +95,7 @@ bool zmDbConnect() {
mysql_close(&dbconn);
return false;
}
if ( mysql_query(&dbconn, "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED") ) {
if (mysql_query(&dbconn, "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")) {
Error("Can't set isolation level: %s", mysql_error(&dbconn));
}
mysql_set_character_set(&dbconn, "utf8");
@ -103,6 +104,20 @@ bool zmDbConnect() {
return zmDbConnected;
}
/* Calls to zmDbReconnect must have the lock. */
bool zmDbReconnect() {
if (zmDbConnected) {
mysql_close(&dbconn);
zmDbConnected = false;
}
if (zmDbConnect()) {
Debug(1, "Reconnected to db...");
} else {
Debug(1, "Failed to reconnect to db");
}
return zmDbConnected;
}
void zmDbClose() {
std::lock_guard<std::mutex> lck(db_mutex);
if (zmDbConnected) {
@ -126,14 +141,8 @@ MYSQL_RES *zmDbFetch(const std::string &query) {
if (rc) {
Debug(1, "Can't run query: %s rc:%d, reason:%s", query.c_str(), rc, mysql_error(&dbconn));
if (mysql_ping(&dbconn)) {
zmDbConnected = false;
if (zmDbConnect()) {
Debug(1, "Reconnected to db...");
rc = mysql_query(&dbconn, query.c_str());
} else {
Debug(1, "Faile to reconnect to db");
}
if (mysql_ping(&dbconn) and zmDbReconnect()) {
rc = mysql_query(&dbconn, query.c_str());
}
}
if (rc) {
@ -177,6 +186,11 @@ MYSQL_RES *zmDbRow::fetch(const std::string &query) {
return result_set;
}
/* performs SQL queries. Will repeat if error is LOCK_WAIT_TIMEOUT
* We assume that in general our SQL is properly formed, so errors will
* be due to external factors.
*/
int zmDbDo(const std::string &query) {
std::lock_guard<std::mutex> lck(db_mutex);
if (!zmDbConnected and !zmDbConnect())
@ -184,40 +198,35 @@ int zmDbDo(const std::string &query) {
int rc;
while ((rc = mysql_query(&dbconn, query.c_str())) and !zm_terminate) {
if (mysql_ping(&dbconn)) {
zmDbConnected = false;
zmDbConnect();
}
if (zmDbConnected) {
Logger *logger = Logger::fetch();
Logger::Level oldLevel = logger->databaseLevel();
logger->databaseLevel(Logger::NOLOG);
// Was a connection error
if (!zmDbReconnect()) {
// If we failed. Sleeping 1 sec may be way too much.
sleep(1);
}
} else {
// Not a connection error
Error("Can't run query %s: %s", query.c_str(), mysql_error(&dbconn));
logger->databaseLevel(oldLevel);
if ( (mysql_errno(&dbconn) != ER_LOCK_WAIT_TIMEOUT) ) {
if (mysql_errno(&dbconn) != ER_LOCK_WAIT_TIMEOUT) {
return rc;
}
} // end if connected
} // end if !connected
}
Logger *logger = Logger::fetch();
Logger::Level oldLevel = logger->databaseLevel();
logger->databaseLevel(Logger::NOLOG);
Debug(1, "Success running sql query %s, thread_id: %lu", query.c_str(), db_thread_id);
logger->databaseLevel(oldLevel);
return 1;
}
int zmDbDoInsert(const std::string &query) {
std::lock_guard<std::mutex> lck(db_mutex);
if (!zmDbConnected and !zmDbConnect())
return 0;
int rc;
while ( (rc = mysql_query(&dbconn, query.c_str())) and !zm_terminate) {
while ((rc = mysql_query(&dbconn, query.c_str())) and !zm_terminate) {
if (mysql_ping(&dbconn)) {
zmDbConnected = false;
zmDbConnect();
}
if (zmDbConnected) {
if (!zmDbReconnect()) sleep(1);
} else {
Error("Can't run query %s: %s", query.c_str(), mysql_error(&dbconn));
if ( (mysql_errno(&dbconn) != ER_LOCK_WAIT_TIMEOUT) )
if ((mysql_errno(&dbconn) != ER_LOCK_WAIT_TIMEOUT))
return 0;
}
}
@ -228,13 +237,13 @@ int zmDbDoInsert(const std::string &query) {
int zmDbDoUpdate(const std::string &query) {
std::lock_guard<std::mutex> lck(db_mutex);
if (!zmDbConnected and !zmDbConnect())
return 0;
int rc;
while ( (rc = mysql_query(&dbconn, query.c_str())) and !zm_terminate) {
if (mysql_ping(&dbconn)) {
zmDbConnected = false;
zmDbConnect();
}
if (zmDbConnected) {
if (!zmDbReconnect()) sleep(1);
} else {
Error("Can't run query %s: %s", query.c_str(), mysql_error(&dbconn));
if ( (mysql_errno(&dbconn) != ER_LOCK_WAIT_TIMEOUT) )
return -rc;

View File

@ -389,49 +389,51 @@ int zm_receive_packet(AVCodecContext *context, AVPacket &packet) {
} // end int zm_receive_packet(AVCodecContext *context, AVPacket &packet)
int zm_send_packet_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet) {
int ret;
if ((ret = avcodec_send_packet(context, &packet)) < 0) {
Error("Unable to send packet %s, continuing",
av_make_error_string(ret).c_str());
return ret;
int pkt_ret, frm_ret;
pkt_ret = avcodec_send_packet(context, &packet);
frm_ret = avcodec_receive_frame(context, frame);
if (pkt_ret == 0 && frm_ret == 0) {
// In this api the packet is always consumed, so return packet.bytes
return packet.size;
} else if (pkt_ret != 0 && pkt_ret != AVERROR(EAGAIN)) {
Error("Could not send packet (error %d = %s)", pkt_ret,
av_make_error_string(pkt_ret).c_str());
return pkt_ret;
} else if (frm_ret != 0 && frm_ret != AVERROR(EAGAIN)) {
Error("Could not receive frame (error %d = %s)", frm_ret,
av_make_error_string(frm_ret).c_str());
return frm_ret;
}
if ((ret = avcodec_receive_frame(context, frame)) < 0) {
if (AVERROR(EAGAIN) == ret) {
// The codec may need more samples than it has, perfectly valid
Debug(2, "Codec not ready to give us a frame");
} else {
Error("Could not receive frame (error %d = '%s')", ret,
av_make_error_string(ret).c_str());
}
return ret;
}
// In this api the packet is always consumed, so return packet.bytes
return packet.size;
return 0;
} // end int zm_send_packet_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet)
/* Returns < 0 on error, 0 if codec not ready, 1 on success
*/
int zm_send_frame_receive_packet(AVCodecContext *ctx, AVFrame *frame, AVPacket &packet) {
int ret;
if (((ret = avcodec_send_frame(ctx, frame)) < 0) and frame) {
Error("Could not send frame (error '%s')",
av_make_error_string(ret).c_str());
return ret;
}
int frm_ret, pkt_ret;
if ((ret = avcodec_receive_packet(ctx, &packet)) < 0) {
if (AVERROR(EAGAIN) == ret) {
frm_ret = avcodec_send_frame(ctx, frame);
pkt_ret = avcodec_receive_packet(ctx, &packet);
if (frm_ret != 0 && frame) {
Error("Could not send frame (error '%s')",
av_make_error_string(frm_ret).c_str());
return frm_ret;
} else if (pkt_ret != 0) {
if (pkt_ret == AVERROR(EAGAIN)) {
// The codec may need more samples than it has, perfectly valid
Debug(2, "Codec not ready to give us a packet");
return 0;
} else if (frame) {
// May get EOF if frame is NULL because it signals flushing
Error("Could not receive packet (error %d = '%s')", ret,
av_make_error_string(ret).c_str());
Error("Could not receive packet (error %d = '%s')", pkt_ret,
av_make_error_string(pkt_ret).c_str());
}
zm_av_packet_unref(&packet);
return ret;
return pkt_ret;
}
return 1;
} // end int zm_send_frame_receive_packet

View File

@ -13,14 +13,18 @@ class Server extends ZM_Object {
public $PathToIndex = '';
public $PathToZMS = ZM_PATH_ZMS;
public $PathToApi = ZM_PATH_API;
public $State_Id = 0;
public $State_Id = -1;
public $Status = 'Unknown';
public $CpuLoad;
public $CpuUsagePercent;
public $TotalMem;
public $FreeMem;
public $TotalSwap;
public $FreeSwap;
public $CpuLoad = -1;
public $CpuUserPercent = -1;
public $CpuNicePercent = -1;
public $CpuSystemPercent = -1;
public $CpuIdlePercent = -1;
public $CpuUsagePercent = -1;
public $TotalMem = -1;
public $FreeMem = -1;
public $TotalSwap = -1;
public $FreeSwap = -1;
public $Latitude;
public $Longitude;

View File

@ -272,6 +272,7 @@ function getNormalNavBarHTML($running, $user, $bandwidth_options, $view, $skin)
<ul class="navbar-nav list-inline justify-content-center">
<?php
echo getSysLoadHTML();
echo getCpuUsageHTML();
echo getDbConHTML();
echo getStorageHTML();
echo getRamHTML();
@ -323,6 +324,7 @@ function getCollapsedNavBarHTML($running, $user, $bandwidth_options, $view, $ski
<ul class="nav navbar-nav list-group">
<?php
echo getSysLoadHTML();
echo getCpuUsageHTML();
echo getDbConHTML();
echo getStorageHTML();
echo getRamHTML();
@ -383,6 +385,20 @@ function getCollapsedNavBarHTML($running, $user, $bandwidth_options, $view, $ski
<?php
} // End function getCollapsedNavBarHTML
// Returns the html representing the current cpu Usage Percent
function getCpuUsageHTML() {
$result = '';
if ( !canView('System') ) return $result;
$result .= '<li id="getCpuUsagesHTML" class="CpuUsage nav-item mx-2">'.PHP_EOL;
global $thisServer;
$result .= '&nbsp;'.translate('Cpu').': '.number_format($thisServer->CpuUsagePercent(), 1, '.', '').'%'.PHP_EOL;
$result .= '</li>'.PHP_EOL;
return $result;
}
// Returns the html representing the current unix style system load
function getSysLoadHTML() {
$result = '';
@ -390,7 +406,8 @@ function getSysLoadHTML() {
$result .= '<li id="getSysLoadHTML" class="Load nav-item mx-2">'.PHP_EOL;
$result .= '<i class="material-icons md-18">trending_up</i>'.PHP_EOL;
$result .= '&nbsp;'.translate('Load').': '.number_format(getLoad(), 2, '.', '').PHP_EOL;
global $thisServer;
$result .= '&nbsp;'.translate('Load').': '.number_format($thisServer->CpuLoad(), 2, '.', '').PHP_EOL;
$result .= '</li>'.PHP_EOL;
return $result;

View File

@ -942,6 +942,10 @@ function watchFullscreen() {
}
}
function watchAllEvents() {
window.location.replace(document.getElementById('allEventsBtn').getAttribute('data-url'));
}
var intervalId;
var secondsToCycle = 0;

View File

@ -372,6 +372,8 @@ if ($streamMode == 'jpeg') {
<button type="button" id="fullscreenBtn" title="<?php echo translate('Fullscreen') ?>" class="avail" data-on-click="watchFullscreen">
<i class="material-icons md-18">fullscreen</i>
</button>
<button type="button" id="allEventsBtn" title="<?php echo translate('All Events') ?>" class="avail" data-on-click="watchAllEvents" data-url="?view=events&page=1&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Battr%5D=Monitor&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bop%5D=%3D&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bval%5D=<?php echo $monitor->Id()?>&filter%5BQuery%5D%5Bsort_asc%5D=1&filter%5BQuery%5D%5Bsort_field%5D=StartDateTime&filter%5BQuery%5D%5Bskip_locked%5D=&filter%5BQuery%5D%5Blimit%5D=0"><?php echo translate('All Events') ?>
</button>
<?php
} // end if streamMode==jpeg
?>