Merge branch 'max_queue_size'
This commit is contained in:
commit
1d99bd5cb3
|
@ -497,11 +497,12 @@ CREATE TABLE `Monitors` (
|
||||||
`LabelX` smallint(5) unsigned NOT NULL default '0',
|
`LabelX` smallint(5) unsigned NOT NULL default '0',
|
||||||
`LabelY` smallint(5) unsigned NOT NULL default '0',
|
`LabelY` smallint(5) unsigned NOT NULL default '0',
|
||||||
`LabelSize` smallint(5) unsigned NOT NULL DEFAULT '1',
|
`LabelSize` smallint(5) unsigned NOT NULL DEFAULT '1',
|
||||||
`ImageBufferCount` smallint(5) unsigned NOT NULL default '100',
|
`ImageBufferCount` smallint(5) unsigned NOT NULL default '3',
|
||||||
`WarmupCount` smallint(5) unsigned NOT NULL default '25',
|
`MaxImageBufferCount` smallint(5) unsigned NOT NULL default '0',
|
||||||
|
`WarmupCount` smallint(5) unsigned NOT NULL default '0',
|
||||||
`PreEventCount` smallint(5) unsigned NOT NULL default '10',
|
`PreEventCount` smallint(5) unsigned NOT NULL default '10',
|
||||||
`PostEventCount` smallint(5) unsigned NOT NULL default '10',
|
`PostEventCount` smallint(5) unsigned NOT NULL default '10',
|
||||||
`StreamReplayBuffer` int(10) unsigned NOT NULL default '1000',
|
`StreamReplayBuffer` int(10) unsigned NOT NULL default '0',
|
||||||
`AlarmFrameCount` smallint(5) unsigned NOT NULL default '1',
|
`AlarmFrameCount` smallint(5) unsigned NOT NULL default '1',
|
||||||
`SectionLength` int(10) unsigned NOT NULL default '600',
|
`SectionLength` int(10) unsigned NOT NULL default '600',
|
||||||
`MinSectionLength` int(10) unsigned NOT NULL default '10',
|
`MinSectionLength` int(10) unsigned NOT NULL default '10',
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
--
|
||||||
|
-- Add MaxImageBufferCount, set it to ImageBufferCount if that was large and set ImageBufferCount to 3
|
||||||
|
--
|
||||||
|
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||||
|
AND table_name = 'Monitors'
|
||||||
|
AND column_name = 'MaxImageBufferCount'
|
||||||
|
) > 0,
|
||||||
|
"SELECT 'Column MaxImageBufferCount already exists in Monitors'",
|
||||||
|
"ALTER TABLE `Monitors` ADD `MaxImageBufferCount` smallint(5) unsigned NOT NULL default '0' AFTER `ImageBufferCount`"
|
||||||
|
));
|
||||||
|
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
|
||||||
|
UPDATE `Monitors` SET MaxImageBufferCount=ImageBufferCount WHERE ImageBufferCount >= 20;
|
||||||
|
UPDATE `Monitors` SET ImageBufferCount = 3;
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
%global _hardened_build 1
|
%global _hardened_build 1
|
||||||
|
|
||||||
Name: zoneminder
|
Name: zoneminder
|
||||||
Version: 1.35.21
|
Version: 1.35.22
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: A camera monitoring and analysis tool
|
Summary: A camera monitoring and analysis tool
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
|
|
|
@ -85,7 +85,7 @@ std::string load_monitor_sql =
|
||||||
"`RecordAudio`, "
|
"`RecordAudio`, "
|
||||||
"`Brightness`, `Contrast`, `Hue`, `Colour`, "
|
"`Brightness`, `Contrast`, `Hue`, `Colour`, "
|
||||||
"`EventPrefix`, `LabelFormat`, `LabelX`, `LabelY`, `LabelSize`,"
|
"`EventPrefix`, `LabelFormat`, `LabelX`, `LabelY`, `LabelSize`,"
|
||||||
"`ImageBufferCount`, `WarmupCount`, `PreEventCount`, `PostEventCount`, `StreamReplayBuffer`, `AlarmFrameCount`, "
|
"`ImageBufferCount`, `MaxImageBufferCount`, `WarmupCount`, `PreEventCount`, `PostEventCount`, `StreamReplayBuffer`, `AlarmFrameCount`, "
|
||||||
"`SectionLength`, `MinSectionLength`, `FrameSkip`, `MotionFrameSkip`, "
|
"`SectionLength`, `MinSectionLength`, `FrameSkip`, `MotionFrameSkip`, "
|
||||||
"`FPSReportInterval`, `RefBlendPerc`, `AlarmRefBlendPerc`, `TrackMotion`, `Exif`,"
|
"`FPSReportInterval`, `RefBlendPerc`, `AlarmRefBlendPerc`, `TrackMotion`, `Exif`,"
|
||||||
"`RTSPServer`, `RTSPStreamName`,"
|
"`RTSPServer`, `RTSPStreamName`,"
|
||||||
|
@ -327,6 +327,7 @@ Monitor::Monitor()
|
||||||
label_coord(Coord(0,0)),
|
label_coord(Coord(0,0)),
|
||||||
label_size(0),
|
label_size(0),
|
||||||
image_buffer_count(0),
|
image_buffer_count(0),
|
||||||
|
max_image_buffer_count(0),
|
||||||
warmup_count(0),
|
warmup_count(0),
|
||||||
pre_event_count(0),
|
pre_event_count(0),
|
||||||
post_event_count(0),
|
post_event_count(0),
|
||||||
|
@ -431,7 +432,7 @@ Monitor::Monitor()
|
||||||
"RecordAudio, "
|
"RecordAudio, "
|
||||||
"Brightness, Contrast, Hue, Colour, "
|
"Brightness, Contrast, Hue, Colour, "
|
||||||
"EventPrefix, LabelFormat, LabelX, LabelY, LabelSize,"
|
"EventPrefix, LabelFormat, LabelX, LabelY, LabelSize,"
|
||||||
"ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, "
|
"ImageBufferCount, `MaxImageBufferCount`, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, "
|
||||||
"SectionLength, MinSectionLength, FrameSkip, MotionFrameSkip, "
|
"SectionLength, MinSectionLength, FrameSkip, MotionFrameSkip, "
|
||||||
"FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif,"
|
"FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif,"
|
||||||
"`RTSPServer`,`RTSPStreamName`,
|
"`RTSPServer`,`RTSPStreamName`,
|
||||||
|
@ -579,10 +580,14 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
||||||
label_size = atoi(dbrow[col]); col++;
|
label_size = atoi(dbrow[col]); col++;
|
||||||
|
|
||||||
image_buffer_count = atoi(dbrow[col]); col++;
|
image_buffer_count = atoi(dbrow[col]); col++;
|
||||||
|
max_image_buffer_count = atoi(dbrow[col]); col++;
|
||||||
warmup_count = atoi(dbrow[col]); col++;
|
warmup_count = atoi(dbrow[col]); col++;
|
||||||
pre_event_count = atoi(dbrow[col]); col++;
|
pre_event_count = atoi(dbrow[col]); col++;
|
||||||
packetqueue.setMaxVideoPackets(pre_event_count);
|
packetqueue.setPreEventVideoPackets(pre_event_count);
|
||||||
|
packetqueue.setMaxVideoPackets(max_image_buffer_count);
|
||||||
|
|
||||||
packetqueue.setKeepKeyframes(videowriter == PASSTHROUGH);
|
packetqueue.setKeepKeyframes(videowriter == PASSTHROUGH);
|
||||||
|
|
||||||
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++;
|
||||||
|
@ -590,7 +595,6 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
||||||
alarm_frame_count = 1;
|
alarm_frame_count = 1;
|
||||||
else if ( alarm_frame_count > MAX_PRE_ALARM_FRAMES )
|
else if ( alarm_frame_count > MAX_PRE_ALARM_FRAMES )
|
||||||
alarm_frame_count = MAX_PRE_ALARM_FRAMES;
|
alarm_frame_count = MAX_PRE_ALARM_FRAMES;
|
||||||
pre_event_buffer_count = pre_event_count + alarm_frame_count + warmup_count - 1;
|
|
||||||
|
|
||||||
section_length = atoi(dbrow[col]); col++;
|
section_length = atoi(dbrow[col]); col++;
|
||||||
min_section_length = atoi(dbrow[col]); col++;
|
min_section_length = atoi(dbrow[col]); col++;
|
||||||
|
@ -639,9 +643,9 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
||||||
|
|
||||||
// Should maybe store this for later use
|
// Should maybe store this for later use
|
||||||
std::string monitor_dir = stringtf("%s/%d", storage->Path(), id);
|
std::string monitor_dir = stringtf("%s/%d", storage->Path(), id);
|
||||||
LoadCamera();
|
|
||||||
|
|
||||||
if ( purpose != QUERY ) {
|
if ( purpose != QUERY ) {
|
||||||
|
LoadCamera();
|
||||||
Zone **zones = 0;
|
Zone **zones = 0;
|
||||||
int n_zones = Zone::Load(this, zones);
|
int n_zones = Zone::Load(this, zones);
|
||||||
this->AddZones(n_zones, zones);
|
this->AddZones(n_zones, zones);
|
||||||
|
@ -676,7 +680,6 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
||||||
}
|
}
|
||||||
} // end if purpose
|
} // end if purpose
|
||||||
|
|
||||||
|
|
||||||
Debug(1, "Loaded monitor %d(%s), %d zones", id, name, n_zones);
|
Debug(1, "Loaded monitor %d(%s), %d zones", id, name, n_zones);
|
||||||
} // Monitor::Load
|
} // Monitor::Load
|
||||||
|
|
||||||
|
@ -3125,7 +3128,7 @@ int Monitor::PrimeCapture() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug(2, "Video stream id is %d, audio is %d, minimum_packets to keep in buffer %d",
|
Debug(2, "Video stream id is %d, audio is %d, minimum_packets to keep in buffer %d",
|
||||||
video_stream_id, audio_stream_id, pre_event_buffer_count);
|
video_stream_id, audio_stream_id, pre_event_count);
|
||||||
|
|
||||||
if (rtsp_server) {
|
if (rtsp_server) {
|
||||||
if (video_stream_id >= 0) {
|
if (video_stream_id >= 0) {
|
||||||
|
|
|
@ -292,10 +292,9 @@ protected:
|
||||||
char label_format[64]; // The format of the timestamp on the images
|
char label_format[64]; // The format of the timestamp on the images
|
||||||
Coord label_coord; // The coordinates of the timestamp on the images
|
Coord label_coord; // The coordinates of the timestamp on the images
|
||||||
int label_size; // Size of the timestamp on the images
|
int label_size; // Size of the timestamp on the images
|
||||||
int32_t image_buffer_count; // Size of circular image buffer, at least twice the size of the pre_event_count
|
int32_t image_buffer_count; // Size of circular image buffer, kept in /dev/shm
|
||||||
int pre_event_buffer_count; // Size of dedicated circular pre event buffer used when analysis is not performed at capturing framerate,
|
int32_t max_image_buffer_count; // Max # of video packets to keep in packet queue
|
||||||
// value is pre_event_count + alarm_frame_count - 1
|
int warmup_count; // How many images to process before looking for events
|
||||||
int warmup_count; // How many images to process before looking for events
|
|
||||||
int pre_event_count; // How many images to hold and prepend to an alarm event
|
int pre_event_count; // How many images to hold and prepend to an alarm event
|
||||||
int post_event_count; // How many unalarmed images must occur before the alarm state is reset
|
int post_event_count; // How many unalarmed images must occur before the alarm state is reset
|
||||||
int stream_replay_buffer; // How many frames to store to support DVR functions, IGNORED from this object, passed directly into zms now
|
int stream_replay_buffer; // How many frames to store to support DVR functions, IGNORED from this object, passed directly into zms now
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
PacketQueue::PacketQueue():
|
PacketQueue::PacketQueue():
|
||||||
video_stream_id(-1),
|
video_stream_id(-1),
|
||||||
max_video_packet_count(-1),
|
max_video_packet_count(-1),
|
||||||
|
pre_event_video_packet_count(-1),
|
||||||
max_stream_id(-1),
|
max_stream_id(-1),
|
||||||
packet_counts(nullptr),
|
packet_counts(nullptr),
|
||||||
deleting(false),
|
deleting(false),
|
||||||
|
@ -84,26 +85,69 @@ bool PacketQueue::queuePacket(ZMPacket* add_packet) {
|
||||||
Debug(4, "No video keyframe so no one needs us to queue packets.");
|
Debug(4, "No video keyframe so no one needs us to queue packets.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mutex.lock();
|
{
|
||||||
|
std::unique_lock<std::mutex> lck(mutex);
|
||||||
|
|
||||||
pktQueue.push_back(add_packet);
|
if (add_packet->packet.stream_index == video_stream_id) {
|
||||||
packet_counts[add_packet->packet.stream_index] += 1;
|
if ((max_video_packet_count > 0) and (packet_counts[video_stream_id] > max_video_packet_count)) {
|
||||||
Debug(2, "packet counts for %d is %d",
|
Warning("You have set the video packets in the queue to %d. The queue is full. Either Analysis is not keeping up or your camera's keyframe interval is larger than this setting. We are dropping packets.");
|
||||||
add_packet->packet.stream_index,
|
if (add_packet->keyframe) {
|
||||||
packet_counts[add_packet->packet.stream_index]);
|
// Have a new keyframe, so delete everything
|
||||||
|
while ((*pktQueue.begin() != add_packet) and (packet_counts[video_stream_id] > max_video_packet_count)) {
|
||||||
|
ZMPacket *zm_packet = *pktQueue.begin();
|
||||||
|
ZMLockedPacket *lp = new ZMLockedPacket(zm_packet);
|
||||||
|
if (!lp->trylock()) {
|
||||||
|
Debug(1, "Found locked packet when trying to free up video packets. Can't continue");
|
||||||
|
//delete lp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delete lp;
|
||||||
|
|
||||||
for (
|
for (
|
||||||
std::list<packetqueue_iterator *>::iterator iterators_it = iterators.begin();
|
std::list<packetqueue_iterator *>::iterator iterators_it = iterators.begin();
|
||||||
iterators_it != iterators.end();
|
iterators_it != iterators.end();
|
||||||
++iterators_it
|
++iterators_it
|
||||||
) {
|
) {
|
||||||
packetqueue_iterator *iterator_it = *iterators_it;
|
packetqueue_iterator *iterator_it = *iterators_it;
|
||||||
if ( *iterator_it == pktQueue.end() ) {
|
// Have to check each iterator and make sure it doesn't point to the packet we are about to delete
|
||||||
Debug(4, "pointing it %p to back", iterator_it);
|
if ( *(*iterator_it) == zm_packet ) {
|
||||||
--(*iterator_it);
|
Debug(1, "Bumping IT because it is at the front that we are deleting");
|
||||||
}
|
++(*iterators_it);
|
||||||
} // end foreach iterator
|
}
|
||||||
mutex.unlock();
|
} // end foreach iterator
|
||||||
|
|
||||||
|
pktQueue.pop_front();
|
||||||
|
packet_counts[zm_packet->packet.stream_index] -= 1;
|
||||||
|
Debug(1, "Deleting a packet with stream index:%d image_index:%d with keyframe:%d, video frames in queue:%d max: %d, queuesize:%d",
|
||||||
|
zm_packet->packet.stream_index, zm_packet->image_index, zm_packet->keyframe, packet_counts[video_stream_id], max_video_packet_count, pktQueue.size());
|
||||||
|
delete zm_packet;
|
||||||
|
} // end while
|
||||||
|
}
|
||||||
|
} // end if too many video packets
|
||||||
|
if ((max_video_packet_count > 0) and (packet_counts[video_stream_id] > max_video_packet_count)) {
|
||||||
|
Error("Unable to free up older packets. Not queueing this video packet.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // end if this packet is a video packet
|
||||||
|
|
||||||
|
pktQueue.push_back(add_packet);
|
||||||
|
packet_counts[add_packet->packet.stream_index] += 1;
|
||||||
|
Debug(2, "packet counts for %d is %d",
|
||||||
|
add_packet->packet.stream_index,
|
||||||
|
packet_counts[add_packet->packet.stream_index]);
|
||||||
|
|
||||||
|
for (
|
||||||
|
std::list<packetqueue_iterator *>::iterator iterators_it = iterators.begin();
|
||||||
|
iterators_it != iterators.end();
|
||||||
|
++iterators_it
|
||||||
|
) {
|
||||||
|
packetqueue_iterator *iterator_it = *iterators_it;
|
||||||
|
if ( *iterator_it == pktQueue.end() ) {
|
||||||
|
Debug(4, "pointing it %p to back", iterator_it);
|
||||||
|
--(*iterator_it);
|
||||||
|
}
|
||||||
|
} // end foreach iterator
|
||||||
|
} // end lock scope
|
||||||
// We signal on every packet because someday we may analyze sound
|
// We signal on every packet because someday we may analyze sound
|
||||||
Debug(4, "packetqueue queuepacket, unlocked signalling");
|
Debug(4, "packetqueue queuepacket, unlocked signalling");
|
||||||
condition.notify_all();
|
condition.notify_all();
|
||||||
|
@ -126,13 +170,13 @@ void PacketQueue::clearPackets(ZMPacket *add_packet) {
|
||||||
and
|
and
|
||||||
add_packet->keyframe
|
add_packet->keyframe
|
||||||
and
|
and
|
||||||
(packet_counts[video_stream_id] > max_video_packet_count)
|
(packet_counts[video_stream_id] > pre_event_video_packet_count)
|
||||||
and
|
and
|
||||||
*(pktQueue.begin()) != add_packet
|
*(pktQueue.begin()) != add_packet
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Debug(3, "stream index %d ?= video_stream_id %d, keyframe %d, keep_keyframes %d, counts %d > max %d at begin %d",
|
Debug(3, "stream index %d ?= video_stream_id %d, keyframe %d, keep_keyframes %d, counts %d > pre_event_count %d at begin %d",
|
||||||
add_packet->packet.stream_index, video_stream_id, add_packet->keyframe, keep_keyframes, packet_counts[video_stream_id], max_video_packet_count,
|
add_packet->packet.stream_index, video_stream_id, add_packet->keyframe, keep_keyframes, packet_counts[video_stream_id], pre_event_video_packet_count,
|
||||||
( *(pktQueue.begin()) != add_packet )
|
( *(pktQueue.begin()) != add_packet )
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -155,7 +199,7 @@ void PacketQueue::clearPackets(ZMPacket *add_packet) {
|
||||||
|
|
||||||
if (!keep_keyframes) {
|
if (!keep_keyframes) {
|
||||||
// If not doing passthrough, we don't care about starting with a keyframe so logic is simpler
|
// If not doing passthrough, we don't care about starting with a keyframe so logic is simpler
|
||||||
while ((*pktQueue.begin() != add_packet) and (packet_counts[video_stream_id] > max_video_packet_count + tail_count)) {
|
while ((*pktQueue.begin() != add_packet) and (packet_counts[video_stream_id] > pre_event_video_packet_count + tail_count)) {
|
||||||
ZMPacket *zm_packet = *pktQueue.begin();
|
ZMPacket *zm_packet = *pktQueue.begin();
|
||||||
ZMLockedPacket *lp = new ZMLockedPacket(zm_packet);
|
ZMLockedPacket *lp = new ZMLockedPacket(zm_packet);
|
||||||
if (!lp->trylock()) break;
|
if (!lp->trylock()) break;
|
||||||
|
@ -164,7 +208,7 @@ void PacketQueue::clearPackets(ZMPacket *add_packet) {
|
||||||
pktQueue.pop_front();
|
pktQueue.pop_front();
|
||||||
packet_counts[zm_packet->packet.stream_index] -= 1;
|
packet_counts[zm_packet->packet.stream_index] -= 1;
|
||||||
Debug(1, "Deleting a packet with stream index:%d image_index:%d with keyframe:%d, video frames in queue:%d max: %d, queuesize:%d",
|
Debug(1, "Deleting a packet with stream index:%d image_index:%d with keyframe:%d, video frames in queue:%d max: %d, queuesize:%d",
|
||||||
zm_packet->packet.stream_index, zm_packet->image_index, zm_packet->keyframe, packet_counts[video_stream_id], max_video_packet_count, pktQueue.size());
|
zm_packet->packet.stream_index, zm_packet->image_index, zm_packet->keyframe, packet_counts[video_stream_id], pre_event_video_packet_count, pktQueue.size());
|
||||||
delete zm_packet;
|
delete zm_packet;
|
||||||
} // end while
|
} // end while
|
||||||
return;
|
return;
|
||||||
|
@ -201,7 +245,7 @@ void PacketQueue::clearPackets(ZMPacket *add_packet) {
|
||||||
++video_packets_to_delete;
|
++video_packets_to_delete;
|
||||||
Debug(4, "Counted %d video packets. Which would leave %d in packetqueue tail count is %d",
|
Debug(4, "Counted %d video packets. Which would leave %d in packetqueue tail count is %d",
|
||||||
video_packets_to_delete, packet_counts[video_stream_id]-video_packets_to_delete, tail_count);
|
video_packets_to_delete, packet_counts[video_stream_id]-video_packets_to_delete, tail_count);
|
||||||
if (packet_counts[video_stream_id] - video_packets_to_delete <= max_video_packet_count + tail_count) {
|
if (packet_counts[video_stream_id] - video_packets_to_delete <= pre_event_video_packet_count + tail_count) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,7 +265,7 @@ void PacketQueue::clearPackets(ZMPacket *add_packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug(1, "Deleting a packet with stream index:%d image_index:%d with keyframe:%d, video frames in queue:%d max: %d, queuesize:%d",
|
Debug(1, "Deleting a packet with stream index:%d image_index:%d with keyframe:%d, video frames in queue:%d max: %d, queuesize:%d",
|
||||||
zm_packet->packet.stream_index, zm_packet->image_index, zm_packet->keyframe, packet_counts[video_stream_id], max_video_packet_count, pktQueue.size());
|
zm_packet->packet.stream_index, zm_packet->image_index, zm_packet->keyframe, packet_counts[video_stream_id], pre_event_video_packet_count, pktQueue.size());
|
||||||
pktQueue.pop_front();
|
pktQueue.pop_front();
|
||||||
packet_counts[zm_packet->packet.stream_index] -= 1;
|
packet_counts[zm_packet->packet.stream_index] -= 1;
|
||||||
delete zm_packet;
|
delete zm_packet;
|
||||||
|
@ -238,7 +282,7 @@ ZMLockedPacket* PacketQueue::popPacket( ) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
Debug(4, "poPacket Mutex locking");
|
Debug(4, "poPacket Mutex locking");
|
||||||
mutex.lock();
|
std::unique_lock<std::mutex> lck(mutex);
|
||||||
|
|
||||||
ZMPacket *zm_packet = pktQueue.front();
|
ZMPacket *zm_packet = pktQueue.front();
|
||||||
for (
|
for (
|
||||||
|
@ -260,8 +304,6 @@ ZMLockedPacket* PacketQueue::popPacket( ) {
|
||||||
pktQueue.pop_front();
|
pktQueue.pop_front();
|
||||||
packet_counts[zm_packet->packet.stream_index] -= 1;
|
packet_counts[zm_packet->packet.stream_index] -= 1;
|
||||||
|
|
||||||
mutex.unlock();
|
|
||||||
|
|
||||||
return lp;
|
return lp;
|
||||||
} // popPacket
|
} // popPacket
|
||||||
|
|
||||||
|
@ -285,7 +327,7 @@ unsigned int PacketQueue::clear(unsigned int frames_to_keep, int stream_id) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Debug(5, "Locking in clear");
|
Debug(5, "Locking in clear");
|
||||||
mutex.lock();
|
std::unique_lock<std::mutex> lck(mutex);
|
||||||
|
|
||||||
packetqueue_iterator it = pktQueue.end()--; // point to last element instead of end
|
packetqueue_iterator it = pktQueue.end()--; // point to last element instead of end
|
||||||
ZMPacket *zm_packet = nullptr;
|
ZMPacket *zm_packet = nullptr;
|
||||||
|
@ -340,13 +382,7 @@ unsigned int PacketQueue::clear(unsigned int frames_to_keep, int stream_id) {
|
||||||
|
|
||||||
delete_count += 1;
|
delete_count += 1;
|
||||||
} // while our iterator is not the first packet
|
} // while our iterator is not the first packet
|
||||||
zm_packet = nullptr; // tidy up for valgrind
|
|
||||||
Debug(3, "Deleted %d packets, %d remaining", delete_count, pktQueue.size());
|
Debug(3, "Deleted %d packets, %d remaining", delete_count, pktQueue.size());
|
||||||
mutex.unlock();
|
|
||||||
return delete_count;
|
|
||||||
|
|
||||||
Debug(3, "Deleted packets, resulting size is %d", pktQueue.size());
|
|
||||||
mutex.unlock();
|
|
||||||
return delete_count;
|
return delete_count;
|
||||||
} // end unsigned int PacketQueue::clear( unsigned int frames_to_keep, int stream_id )
|
} // end unsigned int PacketQueue::clear( unsigned int frames_to_keep, int stream_id )
|
||||||
|
|
||||||
|
@ -389,7 +425,7 @@ unsigned int PacketQueue::clear(struct timeval *duration, int streamId) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Debug(4, "Locking in clear");
|
Debug(4, "Locking in clear");
|
||||||
mutex.lock();
|
std::unique_lock<std::mutex> lck(mutex);
|
||||||
|
|
||||||
struct timeval keep_from;
|
struct timeval keep_from;
|
||||||
std::list<ZMPacket *>::reverse_iterator it = pktQueue.rbegin();
|
std::list<ZMPacket *>::reverse_iterator it = pktQueue.rbegin();
|
||||||
|
@ -440,7 +476,6 @@ unsigned int PacketQueue::clear(struct timeval *duration, int streamId) {
|
||||||
}
|
}
|
||||||
if ( it == pktQueue.rend() ) {
|
if ( it == pktQueue.rend() ) {
|
||||||
Debug(1, "Didn't find a keyframe before event starttime. keeping all" );
|
Debug(1, "Didn't find a keyframe before event starttime. keeping all" );
|
||||||
mutex.unlock();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,14 +497,10 @@ unsigned int PacketQueue::clear(struct timeval *duration, int streamId) {
|
||||||
} // end foreach iterator
|
} // end foreach iterator
|
||||||
pktQueue.pop_front();
|
pktQueue.pop_front();
|
||||||
packet_counts[zm_packet->packet.stream_index] -= 1;
|
packet_counts[zm_packet->packet.stream_index] -= 1;
|
||||||
//if ( zm_packet->image_index == -1 )
|
delete zm_packet;
|
||||||
delete zm_packet;
|
|
||||||
deleted_frames += 1;
|
deleted_frames += 1;
|
||||||
}
|
}
|
||||||
zm_packet = nullptr;
|
|
||||||
Debug(3, "Deleted %d frames", deleted_frames);
|
Debug(3, "Deleted %d frames", deleted_frames);
|
||||||
mutex.unlock();
|
|
||||||
|
|
||||||
return deleted_frames;
|
return deleted_frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,7 +737,13 @@ bool PacketQueue::is_there_an_iterator_pointing_to_packet(ZMPacket *zm_packet) {
|
||||||
void PacketQueue::setMaxVideoPackets(int p) {
|
void PacketQueue::setMaxVideoPackets(int p) {
|
||||||
max_video_packet_count = p;
|
max_video_packet_count = p;
|
||||||
Debug(1, "Setting max_video_packet_count to %d", p);
|
Debug(1, "Setting max_video_packet_count to %d", p);
|
||||||
if ( max_video_packet_count < 1 )
|
if ( max_video_packet_count < 0 )
|
||||||
max_video_packet_count = 1 ;
|
max_video_packet_count = 0 ;
|
||||||
|
}
|
||||||
|
void PacketQueue::setPreEventVideoPackets(int p) {
|
||||||
|
pre_event_video_packet_count = p;
|
||||||
|
Debug(1, "Setting pre_event_video_packet_count to %d", p);
|
||||||
|
if ( pre_event_video_packet_count < 1 )
|
||||||
|
pre_event_video_packet_count = 1;
|
||||||
// We can simplify a lot of logic in queuePacket if we can assume at least 1 packet in queue
|
// We can simplify a lot of logic in queuePacket if we can assume at least 1 packet in queue
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ class PacketQueue {
|
||||||
|
|
||||||
int video_stream_id;
|
int video_stream_id;
|
||||||
int max_video_packet_count; // allow a negative value to someday mean unlimited
|
int max_video_packet_count; // allow a negative value to someday mean unlimited
|
||||||
|
// This is now a hard limit on the # of video packets to keep in the queue so that we can limit ram
|
||||||
|
int pre_event_video_packet_count; // Was max_video_packet_count
|
||||||
int max_stream_id;
|
int max_stream_id;
|
||||||
int *packet_counts; /* packet count for each stream_id, to keep track of how many video vs audio packets are in the queue */
|
int *packet_counts; /* packet count for each stream_id, to keep track of how many video vs audio packets are in the queue */
|
||||||
bool deleting;
|
bool deleting;
|
||||||
|
@ -52,6 +54,7 @@ class PacketQueue {
|
||||||
|
|
||||||
int addStream();
|
int addStream();
|
||||||
void setMaxVideoPackets(int p);
|
void setMaxVideoPackets(int p);
|
||||||
|
void setPreEventVideoPackets(int p);
|
||||||
void setKeepKeyframes(bool k) { keep_keyframes = k; };
|
void setKeepKeyframes(bool k) { keep_keyframes = k; };
|
||||||
|
|
||||||
bool queuePacket(ZMPacket* packet);
|
bool queuePacket(ZMPacket* packet);
|
||||||
|
|
|
@ -84,6 +84,7 @@ class Monitor extends ZM_Object {
|
||||||
'LabelY' => 0,
|
'LabelY' => 0,
|
||||||
'LabelSize' => 1,
|
'LabelSize' => 1,
|
||||||
'ImageBufferCount' => 3,
|
'ImageBufferCount' => 3,
|
||||||
|
'MaxImageBufferCount' => 0,
|
||||||
'WarmupCount' => 0,
|
'WarmupCount' => 0,
|
||||||
'PreEventCount' => 5,
|
'PreEventCount' => 5,
|
||||||
'PostEventCount' => 5,
|
'PostEventCount' => 5,
|
||||||
|
|
|
@ -441,6 +441,7 @@ $SLANG = array(
|
||||||
'Idle' => 'Idle',
|
'Idle' => 'Idle',
|
||||||
'Ignore' => 'Ignore',
|
'Ignore' => 'Ignore',
|
||||||
'ImageBufferSize' => 'Image Buffer Size (frames)',
|
'ImageBufferSize' => 'Image Buffer Size (frames)',
|
||||||
|
'MaxImageBufferCount' => 'Maximum Image Buffer Size (frames)',
|
||||||
'Image' => 'Image',
|
'Image' => 'Image',
|
||||||
'Images' => 'Images',
|
'Images' => 'Images',
|
||||||
'Include' => 'Include',
|
'Include' => 'Include',
|
||||||
|
@ -1137,6 +1138,19 @@ $OLANG = array(
|
||||||
optionally choose to not decode the H264/H265 packets. This will drastically reduce cpu use
|
optionally choose to not decode the H264/H265 packets. This will drastically reduce cpu use
|
||||||
but will make live view unavailable for this monitor.'
|
but will make live view unavailable for this monitor.'
|
||||||
),
|
),
|
||||||
|
'ImageBufferCount' => array(
|
||||||
|
'Help' => '
|
||||||
|
Number of raw images available in /dev/shm. Currently should be set in the 3-5 range. Used for live viewing.'
|
||||||
|
),
|
||||||
|
'MaxImageBufferCount' => array(
|
||||||
|
'Help' => '
|
||||||
|
Maximum number of video packets that will be held in the packet queue.
|
||||||
|
The packetqueue will normally manage itself, keeping Pre Event Count frames or all since last keyframe if using
|
||||||
|
passthrough mode. You can set a maximum to prevent the monitor from consuming too much ram, but your events might
|
||||||
|
not have all the frames they should if your keyframe interval is larger than this value.
|
||||||
|
You will get errors in your logs about this. So make sure your keyframe interval is low or you have enough ram.
|
||||||
|
'
|
||||||
|
),
|
||||||
|
|
||||||
// 'LANG_DEFAULT' => array(
|
// 'LANG_DEFAULT' => array(
|
||||||
// 'Prompt' => "This is a new prompt for this option",
|
// 'Prompt' => "This is a new prompt for this option",
|
||||||
|
|
|
@ -29,6 +29,7 @@ input[name="newMonitor[Refresh]"],
|
||||||
input[name="newMonitor[LabelX]"],
|
input[name="newMonitor[LabelX]"],
|
||||||
input[name="newMonitor[LabelY]"],
|
input[name="newMonitor[LabelY]"],
|
||||||
input[name="newMonitor[ImageBufferCount]"],
|
input[name="newMonitor[ImageBufferCount]"],
|
||||||
|
input[name="newMonitor[MaxImageBufferCount]"],
|
||||||
input[name="newMonitor[WarmupCount]"],
|
input[name="newMonitor[WarmupCount]"],
|
||||||
input[name="newMonitor[PreEventCount]"],
|
input[name="newMonitor[PreEventCount]"],
|
||||||
input[name="newMonitor[PostEventCount]"],
|
input[name="newMonitor[PostEventCount]"],
|
||||||
|
|
|
@ -48,7 +48,6 @@ function updateMonitorDimensions(element) {
|
||||||
form.elements['newMonitor[Height]'].value = dimensions[1];
|
form.elements['newMonitor[Height]'].value = dimensions[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update_estimated_ram_use();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,9 +139,6 @@ function initPage() {
|
||||||
form.submit();
|
form.submit();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
document.querySelectorAll('input[name="newMonitor[ImageBufferCount]"],input[name="newMonitor[Width]"],input[name="newMonitor[Height]"]').forEach(function(el) {
|
|
||||||
el.oninput = window['update_estimated_ram_use'].bind(el);
|
|
||||||
});
|
|
||||||
|
|
||||||
document.querySelectorAll('select[name="newMonitor[Function]"]').forEach(function(el) {
|
document.querySelectorAll('select[name="newMonitor[Function]"]').forEach(function(el) {
|
||||||
el.onchange = function() {
|
el.onchange = function() {
|
||||||
|
@ -269,15 +265,6 @@ function random_WebColour() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_estimated_ram_use() {
|
|
||||||
var buffer_count = document.querySelectorAll('input[name="newMonitor[ImageBufferCount]"]')[0].value;
|
|
||||||
var width = document.querySelectorAll('input[name="newMonitor[Width]"]')[0].value;
|
|
||||||
var height = document.querySelectorAll('input[name="newMonitor[Height]"]')[0].value;
|
|
||||||
var colours = document.querySelectorAll('select[name="newMonitor[Colours]"]')[0].value;
|
|
||||||
|
|
||||||
document.getElementById('estimated_ram_use').innerHTML = human_filesize(buffer_count * width * height * colours, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateLatitudeAndLongitude(latitude, longitude) {
|
function updateLatitudeAndLongitude(latitude, longitude) {
|
||||||
var form = document.getElementById('contentForm');
|
var form = document.getElementById('contentForm');
|
||||||
form.elements['newMonitor[Latitude]'].value = latitude;
|
form.elements['newMonitor[Latitude]'].value = latitude;
|
||||||
|
|
|
@ -1059,9 +1059,13 @@ echo htmlSelect('newMonitor[OutputContainer]', $videowriter_containers, $monitor
|
||||||
{
|
{
|
||||||
?>
|
?>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-right pr-3"><?php echo translate('ImageBufferSize') ?></td>
|
<td class="text-right pr-3"><?php echo translate('ImageBufferSize'); echo makeHelpLink('ImageBufferCount'); ?></td>
|
||||||
<td><input type="number" name="newMonitor[ImageBufferCount]" value="<?php echo validHtmlStr($monitor->ImageBufferCount()) ?>" min="1"/></td>
|
<td><input type="number" name="newMonitor[ImageBufferCount]" value="<?php echo validHtmlStr($monitor->ImageBufferCount()) ?>" min="1"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-right pr-3"><?php echo translate('MaxImageBufferCount'); echo makeHelpLink('MaxImageBufferCount'); ?></td>
|
||||||
|
<td><input type="number" name="newMonitor[MaxImageBufferCount]" value="<?php echo validHtmlStr($monitor->MaxImageBufferCount()) ?>" min="0"/></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-right pr-3"><?php echo translate('WarmupFrames') ?></td>
|
<td class="text-right pr-3"><?php echo translate('WarmupFrames') ?></td>
|
||||||
<td><input type="number" name="newMonitor[WarmupCount]" value="<?php echo validHtmlStr($monitor->WarmupCount()) ?>" min="0"/></td>
|
<td><input type="number" name="newMonitor[WarmupCount]" value="<?php echo validHtmlStr($monitor->WarmupCount()) ?>" min="0"/></td>
|
||||||
|
@ -1082,10 +1086,6 @@ echo htmlSelect('newMonitor[OutputContainer]', $videowriter_containers, $monitor
|
||||||
<td class="text-right pr-3"><?php echo translate('AlarmFrameCount') ?></td>
|
<td class="text-right pr-3"><?php echo translate('AlarmFrameCount') ?></td>
|
||||||
<td><input type="number" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount()) ?>" min="1"/></td>
|
<td><input type="number" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount()) ?>" min="1"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td class="text-right pr-3"><?php echo translate('Estimated Ram Use') ?></td>
|
|
||||||
<td id="estimated_ram_use"><?php echo human_filesize($monitor->ImageBufferCount() * $monitor->Width() * $monitor->Height() * $monitor->Colours(), 0) ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php
|
<?php
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue