Merge branch 'master' into multistream

This commit is contained in:
Isaac Connor 2022-01-05 18:04:10 -05:00
commit 99900e8c1d
9 changed files with 88 additions and 100 deletions

@ -1 +1 @@
Subproject commit cd7fd49becad6010a1b8466bfebbd93999a39878
Subproject commit 1b40f1661f93f50fd5805f239d1e466a3bcf888f

View File

@ -638,6 +638,7 @@ sub logInit( ;@ ) {
$logger = ZoneMinder::Logger->new() if !$logger;
$logger->initialise(%options);
logSetSignal();
return $logger;
}
sub logReinit {

View File

@ -133,6 +133,9 @@ $serial = $primary_key = 'Id';
DefaultCodec
Latitude
Longitude
RTSPServer
RTSPStreamName
Importance
);
%defaults = (

View File

@ -67,7 +67,7 @@ $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
logInit();
my $log = logInit();
logSetSignal();
my $zm_terminate = 0;
sub TermHandler {
@ -114,7 +114,7 @@ while (!$zm_terminate) {
# We can't get the last capture time so can't be sure it's died, it might just be starting up.
my $startup_time = zmGetStartupTime($monitor);
if (($now - $startup_time) > $Config{ZM_WATCH_MAX_DELAY}) {
Warning(
$log->logPrint(ZoneMinder::Logger::WARNING+$monitor->Importance(),
"Restarting capture daemon for $$monitor{Name}, no image since startup. ".
"Startup time was $startup_time - now $now > $Config{ZM_WATCH_MAX_DELAY}"
);
@ -133,8 +133,9 @@ while (!$zm_terminate) {
my $image_delay = $now - $capture_time;
Debug("Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay");
if ($image_delay > $max_image_delay) {
Warning('Restarting capture daemon for '.$monitor->{Name}.
", time since last capture $image_delay seconds ($now-$capture_time)");
$log->logPrint(ZoneMinder::Logger::WARNING+$monitor->Importance(),
'Restarting capture daemon for '.$monitor->{Name}.
", time since last capture $image_delay seconds ($now-$capture_time)");
$monitor->control('restart');
next;
}
@ -160,10 +161,11 @@ while (!$zm_terminate) {
my $image_delay = $now-$image_time;
Debug("Monitor $monitor->{Id} last analysed $image_delay seconds ago, max is $max_image_delay");
if ($image_delay > $max_image_delay) {
Warning("Analysis daemon for $$monitor{Id} $$monitor{Name} needs restarting,"
." time since last analysis $image_delay seconds ($now-$image_time)");
$monitor->control('restart');
next;
$log->logPrint(ZoneMinder::Logger::WARNING+$monitor->Importance(),
"daemon for $$monitor{Id} $$monitor{Name} needs restarting,"
." time since last analysis $image_delay seconds ($now-$image_time)");
$monitor->control('restart');
next;
}
}

View File

@ -55,7 +55,7 @@ Event::Event(
alarm_frames(0),
alarm_frame_written(false),
tot_score(0),
max_score(0),
max_score(-1),
//path(""),
//snapshit_file(),
//alarm_file(""),
@ -291,6 +291,10 @@ void Event::createNotes(std::string &notes) {
}
} // void Event::createNotes(std::string &notes)
void Event::addNote(const char *cause, const std::string &note) {
noteSetMap[cause].insert(note);
}
bool Event::WriteFrameImage(Image *image, SystemTimePoint timestamp, const char *event_file, bool alarm_frame) const {
int thisquality =
(alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality)) ?
@ -486,12 +490,12 @@ void Event::AddFrame(Image *image,
Debug(1, "frames %d, score %d max_score %d", frames, score, max_score);
// If this is the first frame, we should add a thumbnail to the event directory
if ((frames == 1) || (score > (int)max_score)) {
if ((frames == 1) || (score > max_score)) {
write_to_db = true; // web ui might show this as thumbnail, so db needs to know about it.
Debug(1, "Writing snapshot");
WriteFrameImage(image, timestamp, snapshot_file.c_str());
} else {
Debug(1, "Not Writing snapshot because score %d > max %d", score, max_score);
Debug(1, "Not Writing snapshot because frames %d score %d > max %d", frames, score, max_score);
}
// We are writing an Alarm frame
@ -523,11 +527,15 @@ void Event::AddFrame(Image *image,
bool db_frame = ( frame_type == BULK )
or ( frame_type == ALARM )
or ( frames == 1 )
or ( score > (int)max_score )
or ( score > max_score )
or ( monitor_state == Monitor::ALERT )
or ( monitor_state == Monitor::ALARM )
or ( monitor_state == Monitor::PREALARM );
if (score > max_score) {
max_score = score;
}
if (db_frame) {
Microseconds delta_time = std::chrono::duration_cast<Microseconds>(timestamp - start_time);
Debug(1, "Frame delta is %.2f s - %.2f s = %.2f s, score %u zone_stats.size %zu",
@ -568,9 +576,6 @@ void Event::AddFrame(Image *image,
} // end if frame_type == BULK
} // end if db_frame
if (score > (int) max_score) {
max_score = score;
}
end_time = timestamp;
}

View File

@ -77,8 +77,8 @@ class Event {
int frames;
int alarm_frames;
bool alarm_frame_written;
unsigned int tot_score;
unsigned int max_score;
int tot_score;
int max_score;
std::string path;
std::string snapshot_file;
std::string alarm_file;
@ -110,6 +110,7 @@ class Event {
uint64_t Id() const { return id; }
const std::string &Cause() const { return cause; }
void addNote(const char *cause, const std::string &note);
int Frames() const { return frames; }
int AlarmFrames() const { return alarm_frames; }
@ -123,7 +124,7 @@ class Event {
void updateNotes(const StringSetMap &stringSetMap);
void AddFrame(Image *image,
void AddFrame(Image *image,
SystemTimePoint timestamp,
const std::vector<ZoneStats> &stats,
int score = 0,
@ -134,17 +135,17 @@ class Event {
bool SetPath(Storage *storage);
public:
static std::string getSubPath(tm time) {
std::string subpath = stringtf("%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);
return subpath;
}
static std::string getSubPath(time_t *time) {
tm time_tm = {};
localtime_r(time, &time_tm);
return Event::getSubPath(time_tm);
}
static std::string getSubPath(tm time) {
std::string subpath = stringtf("%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);
return subpath;
}
static std::string getSubPath(time_t *time) {
tm time_tm = {};
localtime_r(time, &time_tm);
return Event::getSubPath(time_tm);
}
const char* getEventFile() const {
return video_file.c_str();

View File

@ -375,7 +375,6 @@ Monitor::Monitor()
first_alarm_count(0),
last_alarm_count(0),
last_signal(false),
last_section_mod(0),
buffer_count(0),
state(IDLE),
last_motion_score(0),
@ -426,7 +425,6 @@ Monitor::Monitor()
event_close_mode = CLOSE_IDLE;
event = nullptr;
last_section_mod = 0;
adaptive_skip = true;
@ -1776,29 +1774,24 @@ bool Monitor::Analyse() {
// FIXME this snap might not be the one that caused the signal change. Need to store that in the packet.
if (signal_change) {
Debug(2, "Signal change, new signal is %d", signal);
const char *signalText = "Unknown";
if (!signal) {
signalText = "Lost";
if (event) {
event->addNote(SIGNAL_CAUSE, "Lost");
Info("%s: %03d - Closing event %" PRIu64 ", signal loss", name.c_str(), analysis_image_count, event->Id());
closeEvent();
last_section_mod = 0;
}
} else {
signalText = "Reacquired";
score += 100;
} else if (function == MOCORD or function == RECORD) {
if (!event) {
if (cause.length()) cause += ", ";
cause += SIGNAL_CAUSE + std::string(": Reacquired");
} else {
event->addNote(SIGNAL_CAUSE, "Reacquired");
}
if (snap->image)
ref_image.Assign(*(snap->image));
}
if (!event) {
if (cause.length()) cause += ", ";
cause += SIGNAL_CAUSE;
}
Event::StringSet noteSet;
noteSet.insert(signalText);
noteSetMap[SIGNAL_CAUSE] = noteSet;
shared_data->state = state = IDLE;
shared_data->active = signal;
if ((function == MODECT or function == MOCORD) and snap->image)
ref_image.Assign(*(snap->image));
} // end if signal change
if (signal) {
@ -1842,27 +1835,14 @@ bool Monitor::Analyse() {
/* try to stay behind the decoder. */
if (decoding_enabled) {
while (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) {
if (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) {
// Need to wait for the decoder thread.
Debug(1, "Waiting for decode");
packetqueue.unlock(packet_lock); // This will delete packet_lock and notify_all
packetqueue.wait();
// Another thread may have moved our it. Unlikely but possible
packet_lock = packetqueue.get_packet(analysis_it);
if (!packet_lock) return false;
snap = packet_lock->packet_;
if (!snap->image and snap->decoded) {
Debug(1, "No image but was decoded, giving up");
delete packet_lock;
return false;
}
} // end while ! decoded
if (zm_terminate) {
delete packet_lock;
// Everything may have changed, just return and start again. This needs to be more RAII
return false;
}
} // end while ! decoded
} // end if decoding enabled
SystemTimePoint timestamp = snap->timestamp;
@ -1878,46 +1858,43 @@ bool Monitor::Analyse() {
motion_frame_skip, capture_fps, analysis_fps_limit);
}
if (!(analysis_image_count % (motion_frame_skip+1))) {
if (snap->image) {
// decoder may not have been able to provide an image
if (!ref_image.Buffer()) {
Debug(1, "Assigning instead of Detecting");
ref_image.Assign(*(snap->image));
} else {
Debug(1, "Detecting motion on image %d, image %p", snap->image_index, snap->image);
// Get new score.
int motion_score = DetectMotion(*(snap->image), zoneSet);
if (snap->image) {
// decoder may not have been able to provide an image
if (!ref_image.Buffer()) {
Debug(1, "Assigning instead of Detecting");
ref_image.Assign(*(snap->image));
} else if (!(analysis_image_count % (motion_frame_skip+1))) {
Debug(1, "Detecting motion on image %d, image %p", snap->image_index, snap->image);
// Get new score.
int motion_score = DetectMotion(*(snap->image), zoneSet);
// lets construct alarm cause. It will contain cause + names of zones alarmed
std::string alarm_cause;
snap->zone_stats.reserve(zones.size());
for (const Zone &zone : zones) {
const ZoneStats &stats = zone.GetStats();
stats.DumpToLog("After detect motion");
snap->zone_stats.push_back(stats);
if (zone.Alarmed()) {
if (!alarm_cause.empty()) alarm_cause += ",";
alarm_cause += std::string(zone.Label());
}
// lets construct alarm cause. It will contain cause + names of zones alarmed
snap->zone_stats.reserve(zones.size());
for (const Zone &zone : zones) {
const ZoneStats &stats = zone.GetStats();
stats.DumpToLog("After detect motion");
snap->zone_stats.push_back(stats);
if (zone.Alarmed()) {
if (!snap->alarm_cause.empty()) snap->alarm_cause += ",";
snap->alarm_cause += std::string(zone.Label());
}
Debug(3, "After motion detection, score:%d last_motion_score(%d), new motion score(%d)",
score, last_motion_score, motion_score);
motion_frame_count += 1;
last_motion_score = motion_score;
if (motion_score) {
if (cause.length()) cause += ", ";
cause += MOTION_CAUSE+std::string(":")+alarm_cause;
noteSetMap[MOTION_CAUSE] = zoneSet;
} // end if motion_score
}
Debug(3, "After motion detection, score:%d last_motion_score(%d), new motion score(%d)",
score, last_motion_score, motion_score);
motion_frame_count += 1;
last_motion_score = motion_score;
if (motion_score) {
if (cause.length()) cause += ", ";
cause += MOTION_CAUSE+std::string(":")+snap->alarm_cause;
noteSetMap[MOTION_CAUSE] = zoneSet;
} // end if motion_score
} else {
Debug(1, "no image so skipping motion detection");
} // end if has image
Debug(1, "Skipped motion detection last motion score was %d", last_motion_score);
}
} else {
Debug(1, "Skipped motion detection last motion score was %d", last_motion_score);
}
Debug(1, "no image so skipping motion detection");
} // end if has image
score += last_motion_score;
} else {
Debug(1, "Not Active(%d) enabled %d active %d doing motion detection: %d",
@ -1926,7 +1903,6 @@ bool Monitor::Analyse() {
);
} // end if active and doing motion detection
if (function == RECORD or function == MOCORD) {
// If doing record, check to see if we need to close the event or not.
if (event) {

View File

@ -390,7 +390,6 @@ protected:
int first_alarm_count;
int last_alarm_count;
bool last_signal;
int last_section_mod;
int buffer_count;
State state;
SystemTimePoint start_time;

View File

@ -57,6 +57,7 @@ class ZMPacket {
int64_t pts; // pts in the packet can be in another time base. This MUST be in AV_TIME_BASE_Q
bool decoded;
std::vector<ZoneStats> zone_stats;
std::string alarm_cause;
public:
AVPacket *av_packet() { return &packet; }