diff --git a/db/zm_update-1.35.14.sql b/db/zm_update-1.35.14.sql index daa8239ff..f3c8bf779 100644 --- a/db/zm_update-1.35.14.sql +++ b/db/zm_update-1.35.14.sql @@ -28,8 +28,8 @@ SET @s = (SELECT IF( AND table_name = 'Monitors' AND column_name = 'TotalEvents' ) > 0, -"SELECT 'Column TotalEvents is already removed from Monitors'", -"ALTER TABLE `Monitors` DROP `TotalEvents`" +"ALTER TABLE `Monitors` DROP `TotalEvents`", +"SELECT 'Column TotalEvents is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; @@ -50,8 +50,8 @@ SET @s = (SELECT IF( AND table_name = 'Monitors' AND column_name = 'TotalEventDiskSpace' ) > 0, -"SELECT 'Column TotalEventDiskSpace is already removed from Monitors'", -"ALTER TABLE `Monitors` DROP `TotalEventDiskSpace`" +"ALTER TABLE `Monitors` DROP `TotalEventDiskSpace`", +"SELECT 'Column TotalEventDiskSpace is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 813c58519..58ca5dbf9 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -36,7 +36,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.36.9 +Version: 1.36.10 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons @@ -430,6 +430,9 @@ ln -sf %{_sysconfdir}/zm/www/zoneminder.nginx.conf %{_sysconfdir}/zm/www/zonemin %dir %attr(755,nginx,nginx) %{_localstatedir}/log/zoneminder %changelog +* Mon Oct 25 2021 Andrew Bauer - 1.36.10-1 +- 1.36.10 release + * Tue Oct 19 2021 Andrew Bauer - 1.36.9-1 - 1.36.9 release diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index 48544a911..c786392ad 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -756,9 +756,9 @@ sub CopyTo { } # end sub CopyTo sub MoveTo { - my ( $self, $NewStorage ) = @_; + my ($self, $NewStorage) = @_; - if ( !$self->canEdit() ) { + if (!$self->canEdit()) { Warning('No permission to move event.'); return 'No permission to move event.'; } @@ -772,11 +772,9 @@ sub MoveTo { $$self{StorageId} = $$NewStorage{Id}; $self->Storage($NewStorage); $error .= $self->save(); - if ( $error ) { - $ZoneMinder::Database::dbh->commit(); + if ($error) { return $error; } - $ZoneMinder::Database::dbh->commit(); $self->delete_files($OldStorage); return $error; } # end sub MoveTo diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index 1e62cb229..aa1371d99 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -358,25 +358,27 @@ sub checkFilter { } } # end if AutoDelete - if ( $filter->{AutoMove} ) { - my $NewStorage = new ZoneMinder::Storage($filter->{AutoMoveTo}); - Info("Moving event $Event->{Id} to datastore $filter->{AutoMoveTo}"); - $_ = $Event->MoveTo($NewStorage); - Error($_) if $_; + if ($filter->{AutoMove}) { + my $NewStorage = ZoneMinder::Storage->find_one(Id=>$filter->{AutoMoveTo}); + if ($NewStorage) { + Info("Moving event $Event->{Id} to datastore $filter->{AutoMoveTo}"); + $_ = $Event->MoveTo($NewStorage); + Error($_) if $_; + } else { + Error("No storage area found for move to operation. AutoMoveTo was $$filter{AutoMoveTo}"); + } } - if ( $filter->{AutoCopy} ) { + if ($filter->{AutoCopy}) { # Copy To is different from MoveTo in that it JUST copies the files # So we still need to update the Event object with the new SecondaryStorageId my $NewStorage = ZoneMinder::Storage->find_one(Id=>$filter->{AutoCopyTo}); if ( $NewStorage ) { Info("Copying event $Event->{Id} to datastore $filter->{AutoCopyTo}"); $_ = $Event->CopyTo($NewStorage); - if ( $_ ) { - $ZoneMinder::Database::dbh->commit(); + if ($_) { Error($_); } else { $Event->save({SecondaryStorageId=>$$NewStorage{Id}}); - $ZoneMinder::Database::dbh->commit(); } } else { Error("No storage area found for copy to operation. AutoCopyTo was $$filter{AutoCopyTo}"); diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 4f89b9fe5..545d173d5 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -92,6 +92,7 @@ std::string load_monitor_sql = "`SignalCheckPoints`, `SignalCheckColour`, `Importance`-1 FROM `Monitors`"; std::string CameraType_Strings[] = { + "Unknown", "Local", "Remote", "File", @@ -99,10 +100,21 @@ std::string CameraType_Strings[] = { "LibVLC", "NVSOCKET", "CURL", - "VNC", + "VNC" +}; + +std::string Function_Strings[] = { + "Unknown", + "None", + "Monitor", + "Modect", + "Record", + "Mocord", + "Nodect" }; std::string State_Strings[] = { + "Unknown", "IDLE", "PREALARM", "ALARM", @@ -204,7 +216,7 @@ bool Monitor::MonitorLink::connect() { shared_data = (SharedData *)mem_ptr; trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); - if ( !shared_data->valid ) { + if (!shared_data->valid) { Debug(3, "Linked memory not initialised by capture daemon"); disconnect(); return false; @@ -220,23 +232,23 @@ bool Monitor::MonitorLink::connect() { } // end bool Monitor::MonitorLink::connect() bool Monitor::MonitorLink::disconnect() { - if ( connected ) { + if (connected) { connected = false; #if ZM_MEM_MAPPED - if ( mem_ptr > (void *)0 ) { - msync( mem_ptr, mem_size, MS_ASYNC ); - munmap( mem_ptr, mem_size ); + if (mem_ptr > (void *)0) { + msync(mem_ptr, mem_size, MS_ASYNC); + munmap(mem_ptr, mem_size); } - if ( map_fd >= 0 ) - close( map_fd ); + if (map_fd >= 0) + close(map_fd); map_fd = -1; #else // ZM_MEM_MAPPED struct shmid_ds shm_data; - if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) { - Debug( 3, "Can't shmctl: %s", strerror(errno) ); - return( false ); + if (shmctl(shm_id, IPC_STAT, &shm_data) < 0) { + Debug(3, "Can't shmctl: %s", strerror(errno)); + return false; } shm_id = 0; @@ -252,7 +264,6 @@ bool Monitor::MonitorLink::disconnect() { Debug(3, "Can't shmdt: %s", strerror(errno)); return false; } - #endif // ZM_MEM_MAPPED mem_size = 0; mem_ptr = nullptr; @@ -484,16 +495,7 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) { function = (Function)atoi(dbrow[col]); col++; enabled = dbrow[col] ? atoi(dbrow[col]) : false; col++; decoding_enabled = dbrow[col] ? atoi(dbrow[col]) : false; col++; - decoding_enabled = !( - ( function == RECORD or function == NODECT ) - and - ( savejpegs == 0 ) - and - ( videowriter == PASSTHROUGH ) - and - !decoding_enabled - ); - Debug(1, "Decoding enabled: %d", decoding_enabled); + // See below after save_jpegs for a recalculation of decoding_enabled ReloadLinkedMonitors(dbrow[col]); col++; @@ -556,6 +558,17 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) { videowriter = (VideoWriter)atoi(dbrow[col]); col++; encoderparams = dbrow[col] ? dbrow[col] : ""; col++; + decoding_enabled = !( + ( function == RECORD or function == NODECT ) + and + ( savejpegs == 0 ) + and + ( videowriter == PASSTHROUGH ) + and + !decoding_enabled + ); + Debug(3, "Decoding enabled: %d function %d %s savejpegs %d videowriter %d", decoding_enabled, function, Function_Strings[function].c_str(), savejpegs, videowriter); + /*"`OutputCodec`, `Encoder`, `OutputContainer`, " */ output_codec = dbrow[col] ? atoi(dbrow[col]) : 0; col++; encoder = dbrow[col] ? dbrow[col] : ""; col++; @@ -898,7 +911,6 @@ std::shared_ptr Monitor::Load(unsigned int p_id, bool load_zones, Purpo } bool Monitor::connect() { - if (mem_ptr != nullptr) { Warning("Already connected. Please call disconnect first."); } @@ -1040,7 +1052,7 @@ bool Monitor::connect() { video_store_data->size = sizeof(VideoStoreData); usedsubpixorder = camera->SubpixelOrder(); // Used in CheckSignal shared_data->valid = true; - } else if ( !shared_data->valid ) { + } else if (!shared_data->valid) { Error("Shared data not initialised by capture daemon for monitor %s", name.c_str()); return false; } diff --git a/src/zm_packetqueue.cpp b/src/zm_packetqueue.cpp index d57346a30..ceef421db 100644 --- a/src/zm_packetqueue.cpp +++ b/src/zm_packetqueue.cpp @@ -24,7 +24,6 @@ #include "zm_ffmpeg.h" #include "zm_packet.h" #include "zm_signal.h" -#include PacketQueue::PacketQueue(): video_stream_id(-1), @@ -87,61 +86,6 @@ bool PacketQueue::queuePacket(std::shared_ptr add_packet) { { std::unique_lock lck(mutex); - if (add_packet->packet.stream_index == video_stream_id) { - if ((max_video_packet_count > 0) and (packet_counts[video_stream_id] > max_video_packet_count)) { - Warning("You have set the max video packets in the queue to %u." - " 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.", max_video_packet_count); - if (add_packet->keyframe) { - // Have a new keyframe, so delete everything - while ((*pktQueue.begin() != add_packet) and (packet_counts[video_stream_id] > max_video_packet_count)) { - std::shared_ptr 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 ( - std::list::iterator iterators_it = iterators.begin(); - iterators_it != iterators.end(); - ++iterators_it - ) { - packetqueue_iterator *iterator_it = *iterators_it; - // Have to check each iterator and make sure it doesn't point to the packet we are about to delete - if ( *(*iterator_it) == zm_packet ) { - Debug(1, "Bumping IT because it is at the front that we are deleting"); - ++(*iterators_it); - } - } // 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:%zu", - zm_packet->packet.stream_index, - zm_packet->image_index, - zm_packet->keyframe, - packet_counts[video_stream_id], - max_video_packet_count, - pktQueue.size()); - } // end while - } - } // end if too many video packets - if (max_video_packet_count > 0) { - while (packet_counts[video_stream_id] > max_video_packet_count) { - Error("Unable to free up older packets. Waiting."); - condition.notify_all(); - condition.wait(lck); - if (deleting or zm_terminate) - 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", @@ -149,25 +93,79 @@ bool PacketQueue::queuePacket(std::shared_ptr add_packet) { packet_counts[add_packet->packet.stream_index]); for ( - std::list::iterator iterators_it = iterators.begin(); + auto 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); - } else { - Debug(4, "it %p not at end", iterator_it); } } // end foreach iterator + + if ( + (add_packet->packet.stream_index == video_stream_id) + and + (max_video_packet_count > 0) + and + (packet_counts[video_stream_id] > max_video_packet_count) + ) { + Warning("You have set the max video packets in the queue to %u." + " The queue is full. Either Analysis is not keeping up or" + " your camera's keyframe interval is larger than this setting." + , max_video_packet_count); + + for ( + auto it = ++pktQueue.begin(); + it != pktQueue.end() and *it != add_packet; + ) { + std::shared_ptr zm_packet = *it; + + ZMLockedPacket *lp = new ZMLockedPacket(zm_packet); + if (!lp->trylock()) { + Debug(1, "Found locked packet when trying to free up video packets. Skipping to next one"); + delete lp; + ++it; + continue; + } + + for ( + auto iterators_it = iterators.begin(); + iterators_it != iterators.end(); + ++iterators_it + ) { + auto iterator_it = *iterators_it; + // Have to check each iterator and make sure it doesn't point to the packet we are about to delete + if ((*iterator_it!=pktQueue.end()) and (*(*iterator_it) == zm_packet)) { + Debug(1, "Bumping IT because it is at the front that we are deleting"); + ++(*iterator_it); + } + } // end foreach iterator + + it = pktQueue.erase(it); + 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:%zu", + zm_packet->packet.stream_index, + zm_packet->image_index, + zm_packet->keyframe, + packet_counts[video_stream_id], + max_video_packet_count, + pktQueue.size()); + + delete lp; + + if (zm_packet->packet.stream_index == video_stream_id) + break; + } // end while + } // end if not able catch up } // end lock scope // We signal on every packet because someday we may analyze sound Debug(4, "packetqueue queuepacket, unlocked signalling"); condition.notify_all(); return true; -} // end bool PacketQueue::queuePacket(ZMPacket* zm_packet) +} // end bool PacketQueue::queuePacket(ZMPacket* zm_packet) void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { // Only do queueCleaning if we are adding a video keyframe, so that we guarantee that there is one. @@ -241,8 +239,8 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { return; } - packetqueue_iterator it = pktQueue.begin(); - packetqueue_iterator next_front = pktQueue.begin(); + auto it = pktQueue.begin(); + auto next_front = pktQueue.begin(); // First packet is special because we know it is a video keyframe and only need to check for lock std::shared_ptr zm_packet = *it; @@ -250,11 +248,10 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { return; } - Debug(1, "trying lock on first packet"); ZMLockedPacket *lp = new ZMLockedPacket(zm_packet); if (lp->trylock()) { int video_packets_to_delete = 0; // This is a count of how many packets we will delete so we know when to stop looking - Debug(1, "Have lock on first packet"); + Debug(4, "Have lock on first packet"); ++it; delete lp; @@ -269,10 +266,14 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { } delete lp; - if (is_there_an_iterator_pointing_to_packet(zm_packet) and (pktQueue.begin() == next_front)) { - Warning("Found iterator at beginning of queue. Some thread isn't keeping up"); +#if 0 + // There are no threads that follow analysis thread. So there cannot be an it pointing here + if (is_there_an_iterator_pointing_to_packet(zm_packet)) { + if (pktQueue.begin() == next_front) + Warning("Found iterator at beginning of queue. Some thread isn't keeping up"); break; } +#endif if (zm_packet->packet.stream_index == video_stream_id) { if (zm_packet->keyframe) { diff --git a/version b/version index 42bce65fd..da140cd3f 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.36.9 +1.36.10 diff --git a/web/api/app/Plugin/Crud b/web/api/app/Plugin/Crud index 14292374c..0bd63fb46 160000 --- a/web/api/app/Plugin/Crud +++ b/web/api/app/Plugin/Crud @@ -1 +1 @@ -Subproject commit 14292374ccf1328f2d5db20897bd06f99ba4d938 +Subproject commit 0bd63fb464957080ead342db58ca9e01532cf1ef diff --git a/web/skins/classic/css/base/views/monitor.css b/web/skins/classic/css/base/views/monitor.css index 7fca80aac..f827af5ca 100644 --- a/web/skins/classic/css/base/views/monitor.css +++ b/web/skins/classic/css/base/views/monitor.css @@ -50,6 +50,7 @@ select.chosen { } tr td:first-child { min-width: 300px; + vertical-align: top; } .OutputContainer { display: none;