Skip to content

Commit

Permalink
Merge branch 'ZoneMinder:master' into patch-474778
Browse files Browse the repository at this point in the history
  • Loading branch information
IgorA100 authored Dec 17, 2024
2 parents 5ead358 + 4dcab65 commit 2a22d22
Show file tree
Hide file tree
Showing 17 changed files with 1,102 additions and 62 deletions.
2 changes: 1 addition & 1 deletion cmake/Modules/Pod2Man.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ MACRO(POD2MAN PODFILE MANFILE SECTION MANPAGE_DEST_PREFIX)

ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz
COMMAND ${GZIP} --best -c ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION} > ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz
COMMAND ${GZIP} -n --best -c ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION} > ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}
)

Expand Down
18 changes: 5 additions & 13 deletions scripts/ZoneMinder/lib/ZoneMinder/Logger.pm
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,6 @@ sub initialise( @ ) {

$this->{initialised} = !undef;

# this function can get called on a previously initialized log Object, so clean any sth's
$this->{sth} = undef;

Debug( 'LogOpts: level='.$codes{$this->{level}}
.'/'.$codes{$this->{effectiveLevel}}
.', screen='.$codes{$this->{termLevel}}
Expand Down Expand Up @@ -476,7 +473,6 @@ sub databaseLevel {
} else {
undef($this->{dbh});
}
$this->{sth} = undef;
$this->{databaseLevel} = $databaseLevel;
}
return $this->{databaseLevel};
Expand Down Expand Up @@ -601,7 +597,6 @@ sub logPrint {

if ( $level <= $this->{databaseLevel} ) {
if ( ! ( $ZoneMinder::Database::dbh and $ZoneMinder::Database::dbh->ping() ) ) {
$this->{sth} = undef;
# Turn this off because zDbConnect will do logging calls.
my $oldlevel = $this->{databaseLevel};
$this->{databaseLevel} = NOLOG;
Expand All @@ -612,15 +607,15 @@ sub logPrint {
$this->{databaseLevel} = $oldlevel;
}

my $sql = 'INSERT INTO Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, NULL )';
$this->{sth} = $ZoneMinder::Database::dbh->prepare_cached($sql) if ! $this->{sth};
if ( !$this->{sth} ) {
my $sql = 'INSERT INTO Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? )';
my $sth = $ZoneMinder::Database::dbh->prepare_cached($sql);
if ( !$sth ) {
$this->{databaseLevel} = NOLOG;
Error("Can't prepare log entry '$sql': ".$ZoneMinder::Database::dbh->errstr());
return;
}

my $res = $this->{sth}->execute(
my $res = $sth->execute(
$seconds+($microseconds/1000000.0),
$this->{id},
($ZoneMinder::Config::Config{ZM_SERVER_ID} ? $ZoneMinder::Config::Config{ZM_SERVER_ID} : undef),
Expand All @@ -629,6 +624,7 @@ sub logPrint {
$codes{$level},
$string,
$this->{fileName},
$line
);
if ( !$res ) {
$this->{databaseLevel} = NOLOG;
Expand Down Expand Up @@ -755,10 +751,6 @@ sub Fatal {
if ( $SIG{TERM} and ( $SIG{TERM} ne 'DEFAULT' ) ) {
$SIG{TERM}();
}
if ( $$this{sth} ) {
$$this{sth}->finish();
$$this{sth} = undef;
}
# I think if we don't disconnect we will leave sockets around in TIME_WAIT
ZoneMinder::Database::zmDbDisconnect();
exit(-1);
Expand Down
2 changes: 1 addition & 1 deletion scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ $fields{model} = undef;
Longitude => undef,
RTSPStreamName => '',
RTSPServer => 0,
Importance => 'Normal',
Importance => q`'Normal'`,
MQTT_Enabled => 0,
MQTT_Subscriptions => q`''`,
);
Expand Down
40 changes: 22 additions & 18 deletions scripts/zmtelemetry.pl.in
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
# ==========================================================================

use strict;
use warnings;
use bytes;
use utf8;

Expand Down Expand Up @@ -67,9 +68,11 @@ if ($help) {
pod2usage(-exitstatus => -1);
}

logInit();
my $dbh = zmDbConnect();

if ($show) {
my %telemetry;
my $dbh = zmDbConnect();
collectData($dbh, \%telemetry);
my $result = jsonEncode(\%telemetry);
print($result);
Expand All @@ -90,6 +93,13 @@ print('ZoneMinder Telemetry Agent starting at '.strftime('%y/%m/%d %H:%M:%S', lo
my $lastCheck = $Config{ZM_TELEMETRY_LAST_UPLOAD};

while (1) {
while ( ! ( $dbh and $dbh->ping() ) ) {
Info('Reconnecting to db');
if ( !($dbh = zmDbConnect()) ) {
#What we do here is not that important, so just skip this interval
sleep($interval);
}
}
my $now = time();
my $since_last_check = $now - $lastCheck;
Debug("Last Check time (now($now) - lastCheck($lastCheck)) = $since_last_check > interval($interval) or force($force)");
Expand All @@ -100,23 +110,17 @@ while (1) {
}
if ((($since_last_check) > $interval) or $force) {
print "Collecting data to send to ZoneMinder Telemetry server.\n";
my $dbh = zmDbConnect();
if ($dbh) {
# Build the telemetry hash
# We should keep *BSD systems in mind when calling system commands

my %telemetry;
collectData($dbh, \%telemetry);
my $result = jsonEncode(\%telemetry);

if (sendData($result)) {
ZoneMinder::Database::zmDbDo('UPDATE Config SET Value=? WHERE Name=?',
$now, 'ZM_TELEMETRY_LAST_UPLOAD');
$Config{ZM_TELEMETRY_LAST_UPLOAD} = $now;
}
zmDbDisconnect();
} else {
Error('Failed to open database. Sleeping.');
# Build the telemetry hash
# We should keep *BSD systems in mind when calling system commands

my %telemetry;
collectData($dbh, \%telemetry);
my $result = jsonEncode(\%telemetry);

if (sendData($result)) {
ZoneMinder::Database::zmDbDo('UPDATE Config SET Value=? WHERE Name=?',
$now, 'ZM_TELEMETRY_LAST_UPLOAD');
$Config{ZM_TELEMETRY_LAST_UPLOAD} = $now;
}
} elsif (-t STDIN) {
print "ZoneMinder Telemetry Agent sleeping for $interval seconds because ($now-$lastCheck=$since_last_check > $interval\n";
Expand Down
4 changes: 2 additions & 2 deletions src/zm_eventstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,8 +671,8 @@ void EventStream::processCommand(const CmdMsg *msg) {
FPSeconds elapsed = now - last_fps_update;
if (elapsed.count() > 0) {
actual_fps = (actual_fps + (frame_count - last_frame_count) / elapsed.count())/2;
Debug(1, "actual_fps %f = old + frame_count %d - last %d / elapsed %.2f from %.2f - %.2f", actual_fps, frame_count, last_frame_count,
elapsed.count(), FPSeconds(now.time_since_epoch()).count(), FPSeconds(last_fps_update.time_since_epoch()).count());
Debug(1, "actual_fps %f = old + frame_count %d - last %d / elapsed %.2f from %.2f - %.2f scale %d", actual_fps, frame_count, last_frame_count,
elapsed.count(), FPSeconds(now.time_since_epoch()).count(), FPSeconds(last_fps_update.time_since_epoch()).count(), scale);
last_frame_count = frame_count;
last_fps_update = now;
}
Expand Down
2 changes: 1 addition & 1 deletion src/zm_monitor_onvif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ void Monitor::ONVIF::WaitForMessage() {
int result = proxyEvent.PullMessages(response.SubscriptionReference.Address, nullptr, &tev__PullMessages, tev__PullMessagesResponse);
if (result != SOAP_OK) {
const char *detail = soap_fault_detail(soap);
Debug(1, "Result of getting ONVIF messages=%d soap_fault_string=%s detail=%s",
Debug(1, "Result of getting ONVIF result=%d soap_fault_string=%s detail=%s",
result, soap_fault_string(soap), detail ? detail : "null");
if (result != SOAP_EOF) { //Ignore the timeout error
Error("Failed to get ONVIF messages! %d %s", result, soap_fault_string(soap));
Expand Down
2 changes: 1 addition & 1 deletion src/zm_monitorstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ bool MonitorStream::sendFrame(const std::string &filepath, SystemTimePoint times
TimePoint::duration frame_send_time = send_end_time - send_start_time;

if (frame_send_time > Milliseconds(lround(Milliseconds::period::den / maxfps))) {
Info("Frame send time %" PRIi64 " ms too slow, throttling maxfps to %.2f",
Debug(1, "Frame send time %" PRIi64 " ms too slow, throttling maxfps to %.2f",
static_cast<int64>(std::chrono::duration_cast<Milliseconds>(frame_send_time).count()),
maxfps);
}
Expand Down
28 changes: 28 additions & 0 deletions src/zm_videostore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

extern "C" {
#include <libavutil/time.h>
#include <libavutil/display.h>
}

#include <string>
Expand Down Expand Up @@ -192,7 +193,34 @@ bool VideoStore::open() {
// Only set orientation if doing passthrough, otherwise the frame image will be rotated
Monitor::Orientation orientation = monitor->getOrientation();
if (orientation) {
#if LIBAVCODEC_VERSION_CHECK(59, 37, 100, 37, 100)
int32_t* displaymatrix = static_cast<int32_t*>(av_malloc(sizeof(int32_t)*9));
Debug(3, "Have orientation %d", orientation);
if (orientation == Monitor::ROTATE_0) {
} else if (orientation == Monitor::ROTATE_90) {
av_display_rotation_set(displaymatrix, 90);
} else if (orientation == Monitor::ROTATE_180) {
av_display_rotation_set(displaymatrix, 180);
} else if (orientation == Monitor::ROTATE_270) {
av_display_rotation_set(displaymatrix, 270);
} else {
Warning("Unsupported Orientation(%d)", orientation);
}
#endif
#if LIBAVCODEC_VERSION_CHECK(60, 31, 102, 31, 102)
av_packet_side_data_add(
&video_out_stream->codecpar->coded_side_data,
&video_out_stream->codecpar->nb_coded_side_data,
AV_PKT_DATA_DISPLAYMATRIX,
(int32_t *)displaymatrix, sizeof(int32_t)*9, 0);
#else
#if LIBAVCODEC_VERSION_CHECK(59, 37, 100, 37, 100)
av_stream_add_side_data(video_out_stream,
AV_PKT_DATA_DISPLAYMATRIX,
(uint8_t *)displaymatrix,
sizeof(*displaymatrix));
#endif
#endif
if (orientation == Monitor::ROTATE_0) {
} else if (orientation == Monitor::ROTATE_90) {
ret = av_dict_set(&video_out_stream->metadata, "rotate", "90", 0);
Expand Down
15 changes: 8 additions & 7 deletions src/zmc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,20 +238,21 @@ int main(int argc, char *argv[]) {
result = 0;

for (const std::shared_ptr<Monitor> &monitor : monitors) {
std::string sql = stringtf(
"INSERT INTO Monitor_Status (MonitorId,Status,CaptureFPS,AnalysisFPS,CaptureBandwidth)"
" VALUES (%u, 'Running',0,0,0) ON DUPLICATE KEY UPDATE Status='Running',CaptureFPS=0,AnalysisFPS=0,CaptureBandwidth=0",
monitor->Id());
zmDbDo(sql);

monitor->LoadCamera();

if (!monitor->connect()) {
while (!monitor->connect()) {
Warning("Couldn't connect to monitor %d", monitor->Id());
sleep(1);
}
SystemTimePoint now = std::chrono::system_clock::now();
monitor->SetStartupTime(now);

std::string sql = stringtf(
"INSERT INTO Monitor_Status (MonitorId,Status,CaptureFPS,AnalysisFPS,CaptureBandwidth)"
" VALUES (%u, 'Running',0,0,0) ON DUPLICATE KEY UPDATE Status='Running',CaptureFPS=0,AnalysisFPS=0,CaptureBandwidth=0",
monitor->Id());
zmDbDo(sql);

if (monitor->StartupDelay() > 0) {
Debug(1, "Doing startup sleep for %ds", monitor->StartupDelay());
std::this_thread::sleep_for(Seconds(monitor->StartupDelay()));
Expand Down
14 changes: 7 additions & 7 deletions web/ajax/status.php
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ function getNearEvents() {
$filter_sql = $filter->sql();

# When listing, it may make sense to list them in descending order.
# But when viewing Prev should timewise earlier and Next should be after.
# But when viewing Prev should be timewise earlier and Next should be after.
if ( $sortColumn == 'E.Id' or $sortColumn == 'E.StartDateTime' ) {
$sortOrder = 'ASC';
}
Expand All @@ -520,18 +520,18 @@ function getNearEvents() {
INNER JOIN Monitors AS M ON E.MonitorId = M.Id
LEFT JOIN Events_Tags AS ET ON E.Id = ET.EventId
LEFT JOIN Tags AS T ON T.Id = ET.TagId
WHERE '.$sortColumn.'
WHERE E.Id != ? AND '.$sortColumn.'
'.($sortOrder=='ASC'?'<=':'>=').' \''.$event[$_REQUEST['sort_field']].'\'';
if ($filter->sql()) {
$sql .= ' AND ('.$filter->sql().')';
}
$sql .= ' AND E.StartDateTime < ? ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'DESC':'ASC');
$sql .= ' AND E.StartDateTime <= ? ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'DESC':'ASC');
if ( $sortColumn != 'E.Id' ) {
# When sorting by starttime, if we have two events with the same starttime (different monitors) then we should sort secondly by Id
$sql .= ', E.Id DESC';
}
$sql .= ' LIMIT 1';
$result = dbQuery($sql, [$event['StartDateTime']]);
$result = dbQuery($sql, [$eventId, $event['StartDateTime']]);
if ( !$result ) {
ZM\Error('Failed to load previous event using '.$sql);
return $NearEvents;
Expand All @@ -545,18 +545,18 @@ function getNearEvents() {
INNER JOIN Monitors AS M ON E.MonitorId = M.Id
LEFT JOIN Events_Tags AS ET ON E.Id = ET.EventId
LEFT JOIN Tags AS T ON T.Id = ET.TagId
WHERE '.$sortColumn.'
WHERE E.Id != ? AND '.$sortColumn.'
'.($sortOrder=='ASC'?'>=':'<=').' \''.$event[$_REQUEST['sort_field']].'\'';
if ($filter->sql()) {
$sql .= ' AND ('.$filter->sql().')';
}
$sql .= ' AND E.StartDateTime > ? ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'ASC':'DESC');
$sql .= ' AND E.StartDateTime >= ? ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'ASC':'DESC');
if ( $sortColumn != 'E.Id' ) {
# When sorting by starttime, if we have two events with the same starttime (different monitors) then we should sort secondly by Id
$sql .= ', E.Id ASC';
}
$sql .= ' LIMIT 1';
$result = dbQuery($sql, [$event['StartDateTime']]);
$result = dbQuery($sql, [$eventId, $event['StartDateTime']]);
if ( !$result ) {
ZM\Error('Failed to load next event using '.$sql);
return $NearEvents;
Expand Down
5 changes: 5 additions & 0 deletions web/includes/actions/monitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
if (ZM_OPT_X10) {
$x10Monitor = array();
}
if (!empty($_REQUEST['newMonitor']['Id'])) {
// Reuse existing but deleted monitor
$mid = validCardinal($_REQUEST['newMonitor']['Id']);
}
}

# For convenience
Expand Down Expand Up @@ -92,6 +96,7 @@
'TrackMotion' => 0,
'ModectDuringPTZ' => 0,
'Enabled' => 0,
'Deleted' => 0,
'DecodingEnabled' => 0,
'RTSP2WebEnabled' => 0,
'JanusEnabled' => 0,
Expand Down
8 changes: 6 additions & 2 deletions web/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,16 @@
return;
}

# Add CSP Headers
$cspNonce = bin2hex(zm_random_bytes(16));
if (!$view) {
ZM\Debug(1, "Empty view, defaulting to home view");
$view = getHomeView();
header('Location: ?view='.$view);
return;
}

# Add CSP Headers
$cspNonce = bin2hex(zm_random_bytes(16));

if ( $includeFiles = getSkinIncludes('views/'.$view.'.php', true, true) ) {
ob_start();
CSPHeaders($view, $cspNonce);
Expand Down
1 change: 1 addition & 0 deletions web/lang/en_gb.php
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,7 @@
'he_il' => 'Hebrew',
'dk_dk' => 'Danish',
'ro_ro' => 'Romanian',
'no_nb' => 'Norwegian',

);

Expand Down
Loading

0 comments on commit 2a22d22

Please sign in to comment.