Merge branch 'ZoneMinder:master' into janus
This commit is contained in:
commit
9e9bdd183c
|
@ -96,7 +96,7 @@ my $use_log = (($> == 0) || ($> == $web_uid));
|
|||
logInit( toFile=>$use_log?DEBUG:NOLOG );
|
||||
logSetSignal();
|
||||
|
||||
my $interactive = 1;
|
||||
my $interactive = -t STDERR; # interactive if we have IO
|
||||
my $check = 0;
|
||||
my $freshen = 0;
|
||||
my $rename = 0;
|
||||
|
@ -144,7 +144,7 @@ if ( ($check + $freshen + $rename + $zoneFix + $migrateEvents + ($version?1:0))
|
|||
pod2usage(-exitstatus => -1);
|
||||
}
|
||||
|
||||
if ($check and ($Config{ZM_CHECK_FOR_UPDATES} or $interactive) ) {
|
||||
if ($check) {
|
||||
if (!$interactive) {
|
||||
Info('Update agent starting at '.strftime('%y/%m/%d %H:%M:%S', localtime() )."\n");
|
||||
}
|
||||
|
|
|
@ -132,6 +132,7 @@ class Event {
|
|||
|
||||
SystemTimePoint StartTime() const { return start_time; }
|
||||
SystemTimePoint EndTime() const { return end_time; }
|
||||
TimePoint::duration Duration() const { return end_time - start_time; };
|
||||
|
||||
void AddPacket(const std::shared_ptr<ZMPacket> &p);
|
||||
void AddPacket_(const std::shared_ptr<ZMPacket> &p);
|
||||
|
@ -178,18 +179,6 @@ class Event {
|
|||
return pre_alarm_count;
|
||||
}
|
||||
static void EmptyPreAlarmFrames() {
|
||||
#if 0
|
||||
while ( pre_alarm_count > 0 ) {
|
||||
int i = pre_alarm_count - 1;
|
||||
delete pre_alarm_data[i].image;
|
||||
pre_alarm_data[i].image = nullptr;
|
||||
if ( pre_alarm_data[i].alarm_frame ) {
|
||||
delete pre_alarm_data[i].alarm_frame;
|
||||
pre_alarm_data[i].alarm_frame = nullptr;
|
||||
}
|
||||
pre_alarm_count--;
|
||||
}
|
||||
#endif
|
||||
pre_alarm_count = 0;
|
||||
}
|
||||
static void AddPreAlarmFrame(
|
||||
|
@ -198,28 +187,10 @@ class Event {
|
|||
int score=0,
|
||||
Image *alarm_frame=nullptr
|
||||
) {
|
||||
#if 0
|
||||
pre_alarm_data[pre_alarm_count].image = new Image(*image);
|
||||
pre_alarm_data[pre_alarm_count].timestamp = timestamp;
|
||||
pre_alarm_data[pre_alarm_count].score = score;
|
||||
if ( alarm_frame ) {
|
||||
pre_alarm_data[pre_alarm_count].alarm_frame = new Image(*alarm_frame);
|
||||
}
|
||||
#endif
|
||||
pre_alarm_count++;
|
||||
}
|
||||
void SavePreAlarmFrames() {
|
||||
#if 0
|
||||
for ( int i = 0; i < pre_alarm_count; i++ ) {
|
||||
AddFrame(
|
||||
pre_alarm_data[i].image,
|
||||
pre_alarm_data[i].timestamp,
|
||||
pre_alarm_data[i].score,
|
||||
pre_alarm_data[i].alarm_frame);
|
||||
}
|
||||
#endif
|
||||
EmptyPreAlarmFrames();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ZM_EVENT_H
|
||||
|
|
|
@ -1852,6 +1852,12 @@ bool Monitor::Analyse() {
|
|||
packetqueue.increment_it(analysis_it);
|
||||
return false;
|
||||
}
|
||||
// Ready means that we have captured the warmup # of frames
|
||||
if (!Ready()) {
|
||||
Debug(3, "Not ready?");
|
||||
delete packet_lock;
|
||||
return false;
|
||||
}
|
||||
|
||||
// signal is set by capture
|
||||
bool signal = shared_data->signal;
|
||||
|
@ -1860,60 +1866,43 @@ bool Monitor::Analyse() {
|
|||
Debug(3, "Motion detection is enabled signal(%d) signal_change(%d) trigger state(%s) image index %d",
|
||||
signal, signal_change, TriggerState_Strings[trigger_data->trigger_state].c_str(), snap->image_index);
|
||||
|
||||
{ // scope for event lock
|
||||
// Need to guard around event creation/deletion from Reload()
|
||||
std::lock_guard<std::mutex> lck(event_mutex);
|
||||
|
||||
// if we have been told to be OFF, then we are off and don't do any processing.
|
||||
if (trigger_data->trigger_state != TriggerState::TRIGGER_OFF) {
|
||||
Debug(4, "Trigger not OFF state is (%d)", int(trigger_data->trigger_state));
|
||||
// Ready means that we have captured the warmup # of frames
|
||||
if (!Ready()) {
|
||||
Debug(3, "Not ready?");
|
||||
delete packet_lock;
|
||||
return false;
|
||||
}
|
||||
|
||||
int score = 0;
|
||||
std::string cause;
|
||||
Event::StringSetMap noteSetMap;
|
||||
|
||||
#ifdef WITH_GSOAP
|
||||
if (onvif_event_listener && ONVIF_Healthy) {
|
||||
if (ONVIF_Trigger_State) {
|
||||
score += 9;
|
||||
Debug(1, "Triggered on ONVIF");
|
||||
if (!event) {
|
||||
Event::StringSet noteSet;
|
||||
noteSet.insert("ONVIF2");
|
||||
noteSetMap[MOTION_CAUSE] = noteSet;
|
||||
|
||||
event = openEvent(snap, "ONVIF", noteSetMap);
|
||||
cause += "ONVIF";
|
||||
} else {
|
||||
event->addNote(MOTION_CAUSE, "ONVIF2");
|
||||
// Add to cause
|
||||
}
|
||||
// Regardless of previous state, we go to ALARM
|
||||
shared_data->state = state = ALARM;
|
||||
//If the camera isn't going to send an event close, we need to close it here, but only after it has actually triggered an alarm.
|
||||
if (!ONVIF_Closes_Event && state == ALARM)
|
||||
ONVIF_Trigger_State = FALSE;
|
||||
} // end ONVIF_Trigger
|
||||
} // end if (onvif_event_listener && ONVIF_Healthy)
|
||||
#endif
|
||||
|
||||
// Specifically told to be on. Setting the score here will trigger the alarm.
|
||||
// Specifically told to be on. Setting the score here is not enough to trigger the alarm. Must jump directly to ALARM
|
||||
if (trigger_data->trigger_state == TriggerState::TRIGGER_ON) {
|
||||
score += trigger_data->trigger_score;
|
||||
Debug(1, "Triggered on score += %d => %d", trigger_data->trigger_score, score);
|
||||
if (!event) {
|
||||
if (!cause.empty()) cause += ", ";
|
||||
cause += trigger_data->trigger_cause;
|
||||
Event::StringSet noteSet;
|
||||
noteSet.insert(trigger_data->trigger_text);
|
||||
noteSetMap[trigger_data->trigger_cause] = noteSet;
|
||||
event = openEvent(snap, trigger_data->trigger_cause, noteSetMap);
|
||||
Info("%s: %03d - Opening new event %" PRIu64 ", alarm start", name.c_str(), analysis_image_count, event->Id());
|
||||
} else {
|
||||
event->addNote(trigger_data->trigger_cause, trigger_data->trigger_text);
|
||||
// Need to know if we should end the previous and start a new one, or just add the data
|
||||
}
|
||||
shared_data->state = state = ALARM;
|
||||
} // end if trigger_on
|
||||
|
||||
|
@ -1981,14 +1970,21 @@ bool Monitor::Analyse() {
|
|||
|
||||
/* try to stay behind the decoder. */
|
||||
if (decoding_enabled) {
|
||||
if (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) {
|
||||
while (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) {
|
||||
// Need to wait for the decoder thread.
|
||||
// decoder thread might be waiting on the lock for this packet.
|
||||
// So we need to relinquish the lock and wait. Waiting automatically relinquishes the lock
|
||||
// So...
|
||||
Debug(1, "Waiting for decode");
|
||||
packetqueue.unlock(packet_lock); // This will delete packet_lock and notify_all
|
||||
packetqueue.wait();
|
||||
// Everything may have changed, just return and start again. This needs to be more RAII
|
||||
return true;
|
||||
packet_lock->wait();
|
||||
//packetqueue.unlock(packet_lock); // This will delete packet_lock and notify_all
|
||||
//packetqueue.wait();
|
||||
////packet_lock->lock();
|
||||
} // end while ! decoded
|
||||
if (zm_terminate or analysis_thread->Stopped()) {
|
||||
delete packet_lock;
|
||||
return false;
|
||||
}
|
||||
} // end if decoding enabled
|
||||
|
||||
if (Active() and (function == MODECT or function == MOCORD)) {
|
||||
|
@ -2003,7 +1999,6 @@ bool Monitor::Analyse() {
|
|||
}
|
||||
|
||||
if (snap->image) {
|
||||
|
||||
// decoder may not have been able to provide an image
|
||||
if (!ref_image.Buffer()) {
|
||||
Debug(1, "Assigning instead of Detecting");
|
||||
|
@ -2039,6 +2034,7 @@ bool Monitor::Analyse() {
|
|||
if (cause.length()) cause += ", ";
|
||||
cause += MOTION_CAUSE + std::string(":") + snap->alarm_cause;
|
||||
noteSetMap[MOTION_CAUSE] = zoneSet;
|
||||
score += snap->score;
|
||||
} // end if motion_score
|
||||
} else {
|
||||
Debug(1, "Skipped motion detection last motion score was %d", last_motion_score);
|
||||
|
@ -2060,7 +2056,7 @@ bool Monitor::Analyse() {
|
|||
if (event) {
|
||||
Debug(2, "Have event %" PRIu64 " in record", event->Id());
|
||||
|
||||
if (section_length != Seconds(0) && (snap->timestamp - event->StartTime() >= section_length)
|
||||
if (section_length != Seconds(min_section_length) && (event->Duration() >= section_length)
|
||||
&& ((function == MOCORD && event_close_mode != CLOSE_TIME)
|
||||
|| (function == RECORD && event_close_mode == CLOSE_TIME)
|
||||
|| std::chrono::duration_cast<Seconds>(snap->timestamp.time_since_epoch()) % section_length == Seconds(0))) {
|
||||
|
@ -2082,20 +2078,22 @@ bool Monitor::Analyse() {
|
|||
Info("%s: %03d - Opened new event %" PRIu64 ", continuous section start",
|
||||
name.c_str(), analysis_image_count, event->Id());
|
||||
/* To prevent cancelling out an existing alert\prealarm\alarm state */
|
||||
// This ignores current score status. This should all come after the state machine calculations
|
||||
if (state == IDLE) {
|
||||
shared_data->state = state = TAPE;
|
||||
}
|
||||
} // end if ! event
|
||||
} // end if RECORDING
|
||||
|
||||
if ((snap->score > 0) and (function != MONITOR)) {
|
||||
// If motion detecting, score will be > 0 on motion, but if skipping frames, might not be. So also test snap->score
|
||||
if ((score > 0) or ((snap->score > 0) and (function != MONITOR))) {
|
||||
if ((state == IDLE) || (state == TAPE) || (state == PREALARM)) {
|
||||
// If we should end then previous continuous event and start a new non-continuous event
|
||||
if (event && event->Frames()
|
||||
&& !event->AlarmFrames()
|
||||
&& (event_close_mode == CLOSE_ALARM)
|
||||
// FIXME since we won't be including this snap in the event if we close it, we should be looking at event->duration() instead
|
||||
&& ((snap->timestamp - event->StartTime()) >= min_section_length)
|
||||
&& (event->Duration() >= min_section_length)
|
||||
&& ((!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count - 1))) {
|
||||
Info("%s: %03d - Closing event %" PRIu64 ", continuous end, alarm begins",
|
||||
name.c_str(), image_count, event->Id());
|
||||
|
@ -2107,7 +2105,7 @@ bool Monitor::Analyse() {
|
|||
Event::PreAlarmCount(), pre_event_count,
|
||||
event->Frames(),
|
||||
event->AlarmFrames(),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(snap->timestamp - event->StartTime()).count()),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(event->Duration()).count()),
|
||||
static_cast<int64>(Seconds(min_section_length).count()),
|
||||
(event_close_mode == CLOSE_ALARM));
|
||||
}
|
||||
|
@ -2146,8 +2144,8 @@ bool Monitor::Analyse() {
|
|||
if (state == ALARM) {
|
||||
last_alarm_count = analysis_image_count;
|
||||
} // This is needed so post_event_count counts after last alarmed frames while in ALARM not single alarmed frames while ALERT
|
||||
} else if (!score and snap->score == 0) { // snap->score means -1 which means didn't do motion detection so don't do state transition
|
||||
Debug(1, "!score");
|
||||
} else if (!score and (snap->score == 0)) { // snap->score means -1 which means didn't do motion detection so don't do state transition
|
||||
Debug(1, "!score %s", State_Strings[state].c_str());
|
||||
alert_to_alarm_frame_count = alarm_frame_count; // load same value configured for alarm_frame_count
|
||||
|
||||
if (state == ALARM) {
|
||||
|
@ -2157,7 +2155,7 @@ bool Monitor::Analyse() {
|
|||
if (
|
||||
((analysis_image_count - last_alarm_count) > post_event_count)
|
||||
&&
|
||||
((snap->timestamp - event->StartTime()) >= min_section_length)) {
|
||||
(event->Duration() >= min_section_length)) {
|
||||
Info("%s: %03d - Left alarm state (%" PRIu64 ") - %d(%d) images",
|
||||
name.c_str(), analysis_image_count, event->Id(), event->Frames(), event->AlarmFrames());
|
||||
if (
|
||||
|
@ -2202,12 +2200,12 @@ bool Monitor::Analyse() {
|
|||
if (event) {
|
||||
if (noteSetMap.size() > 0)
|
||||
event->updateNotes(noteSetMap);
|
||||
if (section_length != Seconds(0) && (snap->timestamp - event->StartTime() >= section_length)) {
|
||||
if (section_length != Seconds(min_section_length) && (event->Duration() >= section_length)) {
|
||||
Warning("%s: %03d - event %" PRIu64 ", has exceeded desired section length. %" PRIi64 " - %" PRIi64 " = %" PRIi64 " >= %" PRIi64,
|
||||
name.c_str(), analysis_image_count, event->Id(),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(snap->timestamp.time_since_epoch()).count()),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(GetVideoWriterStartTime().time_since_epoch()).count()),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(snap->timestamp - GetVideoWriterStartTime()).count()),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(event->StartTime().time_since_epoch()).count()),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(event->Duration()).count()),
|
||||
static_cast<int64>(Seconds(section_length).count()));
|
||||
closeEvent();
|
||||
event = openEvent(snap, cause, noteSetMap);
|
||||
|
@ -2247,6 +2245,7 @@ bool Monitor::Analyse() {
|
|||
} // end if ( trigger_data->trigger_state != TRIGGER_OFF )
|
||||
|
||||
if (event) event->AddPacket(snap);
|
||||
} // end scope for event_lock
|
||||
|
||||
// In the case where people have pre-alarm frames, the web ui will generate the frame images
|
||||
// from the mp4. So no one will notice anyways.
|
||||
|
@ -2584,7 +2583,8 @@ bool Monitor::Decode() {
|
|||
std::shared_ptr<ZMPacket> packet = packet_lock->packet_;
|
||||
if (packet->codec_type != AVMEDIA_TYPE_VIDEO) {
|
||||
Debug(4, "Not video");
|
||||
packetqueue.unlock(packet_lock);
|
||||
//packetqueue.unlock(packet_lock);
|
||||
delete packet_lock;
|
||||
return true; // Don't need decode
|
||||
}
|
||||
|
||||
|
@ -2690,24 +2690,31 @@ bool Monitor::Decode() {
|
|||
capture_image->Deinterlace_Blend();
|
||||
} else if (deinterlacing_value == 4) {
|
||||
while (!zm_terminate) {
|
||||
// ICON FIXME SHould we not clone decoder_it?
|
||||
ZMLockedPacket *deinterlace_packet_lock = packetqueue.get_packet(decoder_it);
|
||||
if (!deinterlace_packet_lock) {
|
||||
packetqueue.unlock(packet_lock);
|
||||
delete packet_lock;
|
||||
//packetqueue.unlock(packet_lock);
|
||||
return false;
|
||||
}
|
||||
if (deinterlace_packet_lock->packet_->codec_type == packet->codec_type) {
|
||||
capture_image->Deinterlace_4Field(deinterlace_packet_lock->packet_->image, (deinterlacing>>8)&0xff);
|
||||
packetqueue.unlock(deinterlace_packet_lock);
|
||||
delete deinterlace_packet_lock;
|
||||
//packetqueue.unlock(deinterlace_packet_lock);
|
||||
break;
|
||||
}
|
||||
packetqueue.unlock(deinterlace_packet_lock);
|
||||
delete deinterlace_packet_lock;
|
||||
//packetqueue.unlock(deinterlace_packet_lock);
|
||||
packetqueue.increment_it(decoder_it);
|
||||
}
|
||||
if (zm_terminate) return false;
|
||||
if (zm_terminate) {
|
||||
delete packet_lock;
|
||||
return false;
|
||||
}
|
||||
} else if (deinterlacing_value == 5) {
|
||||
capture_image->Deinterlace_Blend_CustomRatio((deinterlacing>>8)&0xff);
|
||||
}
|
||||
}
|
||||
} // end if deinterlacing_value
|
||||
|
||||
if (orientation != ROTATE_0) {
|
||||
Debug(3, "Doing rotation");
|
||||
|
@ -2744,7 +2751,8 @@ bool Monitor::Decode() {
|
|||
shared_data->signal = (capture_image and signal_check_points) ? CheckSignal(capture_image) : true;
|
||||
shared_data->last_write_index = index;
|
||||
shared_data->last_write_time = std::chrono::system_clock::to_time_t(packet->timestamp);
|
||||
packetqueue.unlock(packet_lock);
|
||||
delete packet_lock;
|
||||
//packetqueue.unlock(packet_lock);
|
||||
return true;
|
||||
} // end bool Monitor::Decode()
|
||||
|
||||
|
|
|
@ -348,7 +348,7 @@ return false;
|
|||
return $value === csrf_hash($_COOKIE[$n], $time);
|
||||
case 'key':
|
||||
if (!$GLOBALS['csrf']['key']) {
|
||||
Debug("Checking key: no key set" );
|
||||
ZM\Debug("Checking key: no key set" );
|
||||
return false;
|
||||
}
|
||||
#Debug("Checking sid: $value === " . csrf_hash($GLOBALS['csrf']['key'], $time) );
|
||||
|
|
Loading…
Reference in New Issue