move analysis thread into monitor. populate analysis_it and decoder_it in Prime instead of constantly checking for them. Handle cases where LockedPacket are null due to shutdown

This commit is contained in:
Isaac Connor 2021-03-17 12:47:52 -04:00
parent a8d31ca686
commit dca34544ec
1 changed files with 71 additions and 49 deletions

View File

@ -395,6 +395,7 @@ Monitor::Monitor()
storage(nullptr), storage(nullptr),
videoStore(nullptr), videoStore(nullptr),
analysis_it(nullptr), analysis_it(nullptr),
analysis_thread(nullptr),
decoder_it(nullptr), decoder_it(nullptr),
decoder(nullptr), decoder(nullptr),
n_zones(0), n_zones(0),
@ -1126,12 +1127,11 @@ Monitor::~Monitor() {
disconnect(); disconnect();
} // end if mem_ptr } // end if mem_ptr
if (analysis_it) { // Will be free by packetqueue destructor
packetqueue.free_it(analysis_it); analysis_it = nullptr;
analysis_it = nullptr; decoder_it = nullptr;
}
for ( int i = 0; i < n_zones; i++ ) { for (int i = 0; i < n_zones; i++) {
delete zones[i]; delete zones[i];
} }
delete[] zones; delete[] zones;
@ -1801,7 +1801,6 @@ bool Monitor::Analyse() {
Warning("Shouldn't be doing Analyse when not Enabled"); Warning("Shouldn't be doing Analyse when not Enabled");
return false; return false;
} }
if (!analysis_it) analysis_it = packetqueue.get_video_it(true);
// if have event, send frames until we find a video packet, at which point do analysis. Adaptive skip should only affect which frames we do analysis on. // if have event, send frames until we find a video packet, at which point do analysis. Adaptive skip should only affect which frames we do analysis on.
@ -1959,12 +1958,12 @@ bool Monitor::Analyse() {
Debug(3, "After motion detection, score:%d last_motion_score(%d), new motion score(%d)", Debug(3, "After motion detection, score:%d last_motion_score(%d), new motion score(%d)",
score, last_motion_score, motion_score); score, last_motion_score, motion_score);
motion_frame_count += 1;
} else { } else {
Warning("No image in snap"); Debug(1, "No image in snap, codec likely not ready");
} }
// Why are we updating the last_motion_score too? // Why are we updating the last_motion_score too?
last_motion_score = motion_score; last_motion_score = motion_score;
motion_frame_count += 1;
} else { } else {
Debug(1, "Skipped motion detection"); Debug(1, "Skipped motion detection");
} }
@ -2031,6 +2030,7 @@ bool Monitor::Analyse() {
} }
ZMLockedPacket *lp = packetqueue.get_packet(start_it); ZMLockedPacket *lp = packetqueue.get_packet(start_it);
delete starting_packet_lock; delete starting_packet_lock;
if (!lp) return false;
starting_packet_lock = lp; starting_packet_lock = lp;
starting_packet = lp->packet_; starting_packet = lp->packet_;
} }
@ -2129,6 +2129,11 @@ bool Monitor::Analyse() {
} }
ZMLockedPacket *lp = packetqueue.get_packet(start_it); ZMLockedPacket *lp = packetqueue.get_packet(start_it);
delete starting_packet_lock; delete starting_packet_lock;
if (!lp) {
// Shutting down event will be closed by ~Monitor()
// Perhaps we shouldn't do this.
return false;
}
starting_packet_lock = lp; starting_packet_lock = lp;
starting_packet = lp->packet_; starting_packet = lp->packet_;
} }
@ -2164,7 +2169,7 @@ bool Monitor::Analyse() {
Debug(1, "Staying in %s", State_Strings[state].c_str()); Debug(1, "Staying in %s", State_Strings[state].c_str());
} }
if ( state == ALARM ) { if (state == ALARM) {
last_alarm_count = analysis_image_count; 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 } // This is needed so post_event_count counts after last alarmed frames while in ALARM not single alarmed frames while ALERT
} else { // no score? } else { // no score?
@ -2172,7 +2177,7 @@ bool Monitor::Analyse() {
if (state == ALARM) { if (state == ALARM) {
Info("%s: %03d - Gone into alert state", name, analysis_image_count); Info("%s: %03d - Gone into alert state", name, analysis_image_count);
shared_data->state = state = ALERT; shared_data->state = state = ALERT;
} else if ( state == ALERT ) { } else if (state == ALERT) {
if ( if (
( analysis_image_count-last_alarm_count > post_event_count ) ( analysis_image_count-last_alarm_count > post_event_count )
&& &&
@ -2190,7 +2195,7 @@ bool Monitor::Analyse() {
shared_data->state = state = TAPE; shared_data->state = state = TAPE;
} }
} }
} else if ( state == PREALARM ) { } else if (state == PREALARM) {
// Back to IDLE // Back to IDLE
shared_data->state = state = ((function != MOCORD) ? IDLE : TAPE); shared_data->state = state = ((function != MOCORD) ? IDLE : TAPE);
} else { } else {
@ -2198,19 +2203,19 @@ bool Monitor::Analyse() {
State_Strings[state].c_str(), analysis_image_count, last_alarm_count, post_event_count, State_Strings[state].c_str(), analysis_image_count, last_alarm_count, post_event_count,
timestamp->tv_sec, video_store_data->recording.tv_sec, min_section_length); timestamp->tv_sec, video_store_data->recording.tv_sec, min_section_length);
} }
if ( Event::PreAlarmCount() ) if (Event::PreAlarmCount())
Event::EmptyPreAlarmFrames(); Event::EmptyPreAlarmFrames();
} // end if score or not } // end if score or not
snap->score = score; snap->score = score;
if ( state == PREALARM ) { if (state == PREALARM) {
// Generate analysis images if necessary // Generate analysis images if necessary
if ( (savejpegs > 1) and snap->image ) { if ((savejpegs > 1) and snap->image) {
for ( int i = 0; i < n_zones; i++ ) { for (int i = 0; i < n_zones; i++) {
if ( zones[i]->Alarmed() ) { if (zones[i]->Alarmed()) {
if ( zones[i]->AlarmImage() ) { if (zones[i]->AlarmImage()) {
if ( ! snap->analysis_image ) if (!snap->analysis_image)
snap->analysis_image = new Image(*(snap->image)); snap->analysis_image = new Image(*(snap->image));
snap->analysis_image->Overlay(*(zones[i]->AlarmImage())); snap->analysis_image->Overlay(*(zones[i]->AlarmImage()));
} }
@ -2221,38 +2226,42 @@ bool Monitor::Analyse() {
// incremement pre alarm image count // incremement pre alarm image count
//have_pre_alarmed_frames ++; //have_pre_alarmed_frames ++;
Event::AddPreAlarmFrame(snap->image, *timestamp, score, nullptr); Event::AddPreAlarmFrame(snap->image, *timestamp, score, nullptr);
} else if ( state == ALARM ) { } else if (state == ALARM) {
if ( ( savejpegs > 1 ) and snap->image ) { if ((savejpegs > 1 ) and snap->image) {
for ( int i = 0; i < n_zones; i++ ) { for (int i = 0; i < n_zones; i++) {
if ( zones[i]->Alarmed() ) { if (zones[i]->Alarmed()) {
if ( zones[i]->AlarmImage() ) { if (zones[i]->AlarmImage()) {
if ( ! snap->analysis_image ) if (!snap->analysis_image)
snap->analysis_image = new Image(*(snap->image)); snap->analysis_image = new Image(*(snap->image));
snap->analysis_image->Overlay(*(zones[i]->AlarmImage())); snap->analysis_image->Overlay(*(zones[i]->AlarmImage()));
} }
if ( config.record_event_stats ) if (config.record_event_stats)
zones[i]->RecordStats(event); zones[i]->RecordStats(event);
} // end if zone is alarmed } // end if zone is alarmed
} // end foreach zone } // end foreach zone
} }
if ( noteSetMap.size() > 0 ) if (event) {
event->updateNotes(noteSetMap); if (noteSetMap.size() > 0)
if ( section_length event->updateNotes(noteSetMap);
&& ( ( timestamp->tv_sec - video_store_data->recording.tv_sec ) >= section_length ) if ( section_length
&& ! (image_count % fps_report_interval) && ( ( timestamp->tv_sec - video_store_data->recording.tv_sec ) >= section_length )
) { && ! (image_count % fps_report_interval)
Warning("%s: %03d - event %" PRIu64 ", has exceeded desired section length. %d - %d = %d >= %d", ) {
name, image_count, event->Id(), Warning("%s: %03d - event %" PRIu64 ", has exceeded desired section length. %d - %d = %d >= %d",
timestamp->tv_sec, video_store_data->recording.tv_sec, name, image_count, event->Id(),
timestamp->tv_sec - video_store_data->recording.tv_sec, timestamp->tv_sec, video_store_data->recording.tv_sec,
section_length timestamp->tv_sec - video_store_data->recording.tv_sec,
); section_length
closeEvent(); );
event = new Event(this, *timestamp, cause, noteSetMap); closeEvent();
shared_data->last_event_id = event->Id(); event = new Event(this, *timestamp, cause, noteSetMap);
//set up video store data shared_data->last_event_id = event->Id();
snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile()); //set up video store data
video_store_data->recording = event->StartTime(); snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile());
video_store_data->recording = event->StartTime();
}
} else {
Error("ALARM but no event");
} }
} else if ( state == ALERT ) { } else if ( state == ALERT ) {
@ -2735,7 +2744,6 @@ int Monitor::Capture() {
} // end Monitor::Capture } // end Monitor::Capture
bool Monitor::Decode() { bool Monitor::Decode() {
if (!decoder_it) decoder_it = packetqueue.get_video_it(true);
ZMLockedPacket *packet_lock = packetqueue.get_packet(decoder_it); ZMLockedPacket *packet_lock = packetqueue.get_packet(decoder_it);
if (!packet_lock) return false; if (!packet_lock) return false;
@ -3146,8 +3154,17 @@ int Monitor::PrimeCapture() {
} }
} // end if rtsp_server } // end if rtsp_server
if (decoding_enabled) { if (decoding_enabled) {
decoder = new DecoderThread(this); if (!decoder_it) decoder_it = packetqueue.get_video_it(false);
if (!decoder) decoder = new DecoderThread(this);
} }
if (function != MONITOR) {
if (!analysis_it) analysis_it = packetqueue.get_video_it(false);
if (!analysis_thread) {
Debug(1, "Starting an analysis thread for monitor (%d)", id);
analysis_thread = new AnalysisThread(this);
}
}
} else { } else {
Debug(2, "Failed to prime %d", ret); Debug(2, "Failed to prime %d", ret);
} }
@ -3157,17 +3174,22 @@ int Monitor::PrimeCapture() {
int Monitor::PreCapture() const { return camera->PreCapture(); } int Monitor::PreCapture() const { return camera->PreCapture(); }
int Monitor::PostCapture() const { return camera->PostCapture(); } int Monitor::PostCapture() const { return camera->PostCapture(); }
int Monitor::Close() { int Monitor::Close() {
if ( decoder ) { // Because the stream indexes may change we have to clear out the packetqueue
decoder->Stop(); if (decoder) decoder->Stop();
if (analysis_thread) analysis_thread->Stop();
packetqueue.clear();
if (decoder) {
delete decoder; delete decoder;
} }
if (analysis_thread) {
delete analysis_thread;
}
std::lock_guard<std::mutex> lck(event_mutex); std::lock_guard<std::mutex> lck(event_mutex);
if (event) { if (event) {
Info("%s: image_count:%d - Closing event %" PRIu64 ", shutting down", name, image_count, event->Id()); Info("%s: image_count:%d - Closing event %" PRIu64 ", shutting down", name, image_count, event->Id());
closeEvent(); closeEvent();
} }
if (camera) camera->Close(); if (camera) camera->Close();
packetqueue.clear();
return 1; return 1;
} }