cpplint spacing changes. The real change is in Analysis we move the Ready check to only affect motion detection. This hopefully fixes the massive memory leak when Decoding=OnDemand

pull/3812/head
Isaac Connor 2024-01-30 09:31:28 -05:00
parent c6ff1e9748
commit 5285c6e716
1 changed files with 74 additions and 64 deletions

View File

@ -53,6 +53,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <chrono> #include <chrono>
#include <string>
#include <utility>
#if ZM_MEM_MAPPED #if ZM_MEM_MAPPED
#include <sys/mman.h> #include <sys/mman.h>
@ -76,26 +78,35 @@ struct Namespace namespaces[] =
#endif #endif
// This is the official SQL (and ordering of the fields) to load a Monitor. // This is the official SQL (and ordering of the fields) to load a Monitor.
// It will be used wherever a Monitor dbrow is needed. WHERE conditions can be appended // It will be used wherever a Monitor dbrow is needed.
std::string load_monitor_sql = std::string load_monitor_sql =
"SELECT `Id`, `Name`, `Deleted`, `ServerId`, `StorageId`, `Type`, `Capturing`+0, `Analysing`+0, `AnalysisSource`+0, `AnalysisImage`+0," "SELECT `Id`, `Name`, `Deleted`, `ServerId`, `StorageId`, `Type`, "
"`Recording`+0, `RecordingSource`+0, `Decoding`+0, `RTSP2WebEnabled`, `RTSP2WebType`," "`Capturing`+0, `Analysing`+0, `AnalysisSource`+0, `AnalysisImage`+0, "
"`JanusEnabled`, `JanusAudioEnabled`, `Janus_Profile_Override`, `Janus_Use_RTSP_Restream`, `Janus_RTSP_User`, `Janus_RTSP_Session_Timeout`, " "`Recording`+0, `RecordingSource`+0, `Decoding`+0, "
"`LinkedMonitors`, `EventStartCommand`, `EventEndCommand`, `AnalysisFPSLimit`, `AnalysisUpdateDelay`, `MaxFPS`, `AlarmMaxFPS`," "`RTSP2WebEnabled`, `RTSP2WebType`, "
"`Device`, `Channel`, `Format`, `V4LMultiBuffer`, `V4LCapturesPerFrame`, " // V4L Settings "`JanusEnabled`, `JanusAudioEnabled`, `Janus_Profile_Override`, "
"`Protocol`, `Method`, `Options`, `User`, `Pass`, `Host`, `Port`, `Path`, `SecondPath`, `Width`, `Height`, `Colours`, `Palette`, `Orientation`+0, `Deinterlacing`, " "`Janus_Use_RTSP_Restream`, `Janus_RTSP_User`, `Janus_RTSP_Session_Timeout`, "
"`LinkedMonitors`, `EventStartCommand`, `EventEndCommand`, `AnalysisFPSLimit`,"
"`AnalysisUpdateDelay`, `MaxFPS`, `AlarmMaxFPS`,"
"`Device`, `Channel`, `Format`, `V4LMultiBuffer`, `V4LCapturesPerFrame`, "
"`Protocol`, `Method`, `Options`, `User`, `Pass`, `Host`, `Port`, `Path`, "
"`SecondPath`, `Width`, `Height`, `Colours`, `Palette`, `Orientation`+0, "
"`Deinterlacing`, "
"`Decoder`, `DecoderHWAccelName`, `DecoderHWAccelDevice`, `RTSPDescribe`, " "`Decoder`, `DecoderHWAccelName`, `DecoderHWAccelDevice`, `RTSPDescribe`, "
"`SaveJPEGs`, `VideoWriter`, `EncoderParameters`, " "`SaveJPEGs`, `VideoWriter`, `EncoderParameters`, "
"`OutputCodec`, `Encoder`, `OutputContainer`, " "`OutputCodec`, `Encoder`, `OutputContainer`, "
"`RecordAudio`, " "`RecordAudio`, "
"`Brightness`, `Contrast`, `Hue`, `Colour`, " "`Brightness`, `Contrast`, `Hue`, `Colour`, "
"`EventPrefix`, `LabelFormat`, `LabelX`, `LabelY`, `LabelSize`," "`EventPrefix`, `LabelFormat`, `LabelX`, `LabelY`, `LabelSize`,"
"`ImageBufferCount`, `MaxImageBufferCount`, `WarmupCount`, `PreEventCount`, `PostEventCount`, `StreamReplayBuffer`, `AlarmFrameCount`, " "`ImageBufferCount`, `MaxImageBufferCount`, `WarmupCount`, `PreEventCount`, "
"`SectionLength`, `SectionLengthWarn`, `MinSectionLength`, `FrameSkip`, `MotionFrameSkip`, " "`PostEventCount`, `StreamReplayBuffer`, `AlarmFrameCount`, "
"`SectionLength`, `SectionLengthWarn`, `MinSectionLength`, `FrameSkip`,"
"`MotionFrameSkip`, "
"`FPSReportInterval`, `RefBlendPerc`, `AlarmRefBlendPerc`, `TrackMotion`, `Exif`, " "`FPSReportInterval`, `RefBlendPerc`, `AlarmRefBlendPerc`, `TrackMotion`, `Exif`, "
"`Latitude`, `Longitude`, " "`Latitude`, `Longitude`, "
"`RTSPServer`, `RTSPStreamName`, `ONVIF_Alarm_Text`," "`RTSPServer`, `RTSPStreamName`, `ONVIF_Alarm_Text`,"
"`ONVIF_URL`, `ONVIF_Username`, `ONVIF_Password`, `ONVIF_Options`, `ONVIF_Event_Listener`, `use_Amcrest_API`," "`ONVIF_URL`, `ONVIF_Username`, `ONVIF_Password`, `ONVIF_Options`, "
"`ONVIF_Event_Listener`, `use_Amcrest_API`,"
"`SignalCheckPoints`, `SignalCheckColour`, `Importance`-1, ZoneCount " "`SignalCheckPoints`, `SignalCheckColour`, `Importance`-1, ZoneCount "
#if MOSQUITTOPP_FOUND #if MOSQUITTOPP_FOUND
", `MQTT_Enabled`, `MQTT_Subscriptions`" ", `MQTT_Enabled`, `MQTT_Subscriptions`"
@ -161,8 +172,8 @@ std::string TriggerState_Strings[] = {
"Cancel", "On", "Off" "Cancel", "On", "Off"
}; };
Monitor::Monitor() Monitor::Monitor() :
: id(0), id(0),
name(""), name(""),
server_id(0), server_id(0),
storage_id(0), storage_id(0),
@ -411,15 +422,17 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
analysis_fps_limit = dbrow[col] ? strtod(dbrow[col], nullptr) : 0.0; col++; analysis_fps_limit = dbrow[col] ? strtod(dbrow[col], nullptr) : 0.0; col++;
analysis_update_delay = Seconds(strtoul(dbrow[col++], nullptr, 0)); analysis_update_delay = Seconds(strtoul(dbrow[col++], nullptr, 0));
capture_delay = capture_delay =
(dbrow[col] && atof(dbrow[col]) > 0.0) ? std::chrono::duration_cast<Microseconds>(FPSeconds(1 / atof(dbrow[col]))) (dbrow[col] && atof(dbrow[col]) > 0.0) ?
std::chrono::duration_cast<Microseconds>(FPSeconds(1 / atof(dbrow[col])))
: Microseconds(0); : Microseconds(0);
col++; col++;
alarm_capture_delay = alarm_capture_delay =
(dbrow[col] && atof(dbrow[col]) > 0.0) ? std::chrono::duration_cast<Microseconds>(FPSeconds(1 / atof(dbrow[col]))) (dbrow[col] && atof(dbrow[col]) > 0.0) ?
std::chrono::duration_cast<Microseconds>(FPSeconds(1 / atof(dbrow[col])))
: Microseconds(0); : Microseconds(0);
col++; col++;
/* "Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, " // V4L Settings */ /* "Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, " */
device = dbrow[col] ? dbrow[col] : ""; col++; device = dbrow[col] ? dbrow[col] : ""; col++;
channel = atoi(dbrow[col]); col++; channel = atoi(dbrow[col]); col++;
format = atoi(dbrow[col]); col++; format = atoi(dbrow[col]); col++;
@ -504,8 +517,11 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
post_event_count = atoi(dbrow[col]); col++; post_event_count = atoi(dbrow[col]); col++;
stream_replay_buffer = atoi(dbrow[col]); col++; stream_replay_buffer = atoi(dbrow[col]); col++;
alarm_frame_count = atoi(dbrow[col]); col++; alarm_frame_count = atoi(dbrow[col]); col++;
if (alarm_frame_count < 1) alarm_frame_count = 1; if (alarm_frame_count < 1) {
else if (alarm_frame_count > MAX_PRE_ALARM_FRAMES) alarm_frame_count = MAX_PRE_ALARM_FRAMES; alarm_frame_count = 1;
} else if (alarm_frame_count > MAX_PRE_ALARM_FRAMES) {
alarm_frame_count = MAX_PRE_ALARM_FRAMES;
}
/* "SectionLength, MinSectionLength, FrameSkip, MotionFrameSkip, " */ /* "SectionLength, MinSectionLength, FrameSkip, MotionFrameSkip, " */
section_length = Seconds(atoi(dbrow[col])); col++; section_length = Seconds(atoi(dbrow[col])); col++;
@ -565,7 +581,7 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
importance = dbrow[col] ? atoi(dbrow[col]) : 0; col++; importance = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
if (importance < 0) importance = 0; // Should only be >= 0 if (importance < 0) importance = 0; // Should only be >= 0
zone_count = dbrow[col] ? atoi(dbrow[col]) : 0;// col++; zone_count = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
#if MOSQUITTOPP_FOUND #if MOSQUITTOPP_FOUND
mqtt_enabled = (*dbrow[col] != '0'); col++; mqtt_enabled = (*dbrow[col] != '0'); col++;
@ -583,11 +599,12 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
last_signal = true; // Defaulting to having signal so that we don't get a signal change on the first frame. last_signal = true; // Defaulting to having signal so that we don't get a signal change on the first frame.
// Instead initial failure to capture will cause a loss of signal change which I think makes more sense. // Instead initial failure to capture will cause a loss of signal change which I think makes more sense.
if ( strcmp(config.event_close_mode, "time") == 0 ) if (strcmp(config.event_close_mode, "time") == 0) {
event_close_mode = CLOSE_TIME; event_close_mode = CLOSE_TIME;
else if ( strcmp(config.event_close_mode, "alarm") == 0 ) } else if (strcmp(config.event_close_mode, "alarm") == 0) {
event_close_mode = CLOSE_ALARM; event_close_mode = CLOSE_ALARM;
else } else {
}
event_close_mode = CLOSE_IDLE; event_close_mode = CLOSE_IDLE;
// Should maybe store this for later use // Should maybe store this for later use
@ -1941,12 +1958,6 @@ bool Monitor::Analyse() {
packetqueue.increment_it(analysis_it); packetqueue.increment_it(analysis_it);
return false; 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 // signal is set by capture
bool signal = shared_data->signal; bool signal = shared_data->signal;
@ -2091,7 +2102,8 @@ bool Monitor::Analyse() {
} }
} // end if decoding enabled } // end if decoding enabled
if (shared_data->analysing > ANALYSING_NONE) { // Ready means that we have captured the warmup # of frames
if ((shared_data->analysing > ANALYSING_NONE) && Ready()) {
Debug(3, "signal and capturing and doing motion detection %d", shared_data->analysing); Debug(3, "signal and capturing and doing motion detection %d", shared_data->analysing);
if (analysis_fps_limit) { if (analysis_fps_limit) {
@ -3571,16 +3583,14 @@ StringVector Monitor::GroupNames() {
#ifdef WITH_GSOAP #ifdef WITH_GSOAP
//ONVIF Set Credentials //ONVIF Set Credentials
void Monitor::set_credentials(struct soap *soap) void Monitor::set_credentials(struct soap *soap) {
{
soap_wsse_delete_Security(soap); soap_wsse_delete_Security(soap);
soap_wsse_add_Timestamp(soap, NULL, 10); soap_wsse_add_Timestamp(soap, NULL, 10);
soap_wsse_add_UsernameTokenDigest(soap, "Auth", onvif_username.c_str(), onvif_password.c_str()); soap_wsse_add_UsernameTokenDigest(soap, "Auth", onvif_username.c_str(), onvif_password.c_str());
} }
//GSOAP boilerplate //GSOAP boilerplate
int SOAP_ENV__Fault(struct soap *soap, char *faultcode, char *faultstring, char *faultactor, struct SOAP_ENV__Detail *detail, struct SOAP_ENV__Code *SOAP_ENV__Code, struct SOAP_ENV__Reason *SOAP_ENV__Reason, char *SOAP_ENV__Node, char *SOAP_ENV__Role, struct SOAP_ENV__Detail *SOAP_ENV__Detail) int SOAP_ENV__Fault(struct soap *soap, char *faultcode, char *faultstring, char *faultactor, struct SOAP_ENV__Detail *detail, struct SOAP_ENV__Code *SOAP_ENV__Code, struct SOAP_ENV__Reason *SOAP_ENV__Reason, char *SOAP_ENV__Node, char *SOAP_ENV__Role, struct SOAP_ENV__Detail *SOAP_ENV__Detail) {
{
// populate the fault struct from the operation arguments to print it // populate the fault struct from the operation arguments to print it
soap_fault(soap); soap_fault(soap);
// SOAP 1.1 // SOAP 1.1