Merge branch 'master' into multistream
This commit is contained in:
commit
99900e8c1d
|
@ -1 +1 @@
|
|||
Subproject commit cd7fd49becad6010a1b8466bfebbd93999a39878
|
||||
Subproject commit 1b40f1661f93f50fd5805f239d1e466a3bcf888f
|
|
@ -638,6 +638,7 @@ sub logInit( ;@ ) {
|
|||
$logger = ZoneMinder::Logger->new() if !$logger;
|
||||
$logger->initialise(%options);
|
||||
logSetSignal();
|
||||
return $logger;
|
||||
}
|
||||
|
||||
sub logReinit {
|
||||
|
|
|
@ -133,6 +133,9 @@ $serial = $primary_key = 'Id';
|
|||
DefaultCodec
|
||||
Latitude
|
||||
Longitude
|
||||
RTSPServer
|
||||
RTSPStreamName
|
||||
Importance
|
||||
);
|
||||
|
||||
%defaults = (
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ¬es) {
|
|||
}
|
||||
} // void Event::createNotes(std::string ¬es)
|
||||
|
||||
void Event::addNote(const char *cause, const std::string ¬e) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ¬e);
|
||||
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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
Loading…
Reference in New Issue