From 56588939e76571c760b3b272e4c4c134a2fcdab2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Feb 2026 22:35:50 -0500 Subject: [PATCH] Make clearPackets return false if it can't remove any packets. So that we try again even if we aren't looking at a keyframe. --- src/zm_packetqueue.cpp | 33 ++++++++++++++++++++++----------- src/zm_packetqueue.h | 3 ++- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/zm_packetqueue.cpp b/src/zm_packetqueue.cpp index 7b20635e5..c14fb45dc 100644 --- a/src/zm_packetqueue.cpp +++ b/src/zm_packetqueue.cpp @@ -40,6 +40,7 @@ PacketQueue::PacketQueue(): has_out_of_order_packets_(false), max_keyframe_interval_(0), frames_since_last_keyframe_(0), + clear_packets_pending_(false), next_queue_index_(0) { } @@ -215,7 +216,7 @@ packetqueue_iterator PacketQueue::deletePacket(packetqueue_iterator it) { return pktQueue.erase(it); } -void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { +bool PacketQueue::clearPackets(const std::shared_ptr &add_packet) { // Packets removed from the queue are collected here and destroyed after the // mutex is released, so that expensive ZMPacket destructors (freeing images, // av packets) don't run while the queue is locked. @@ -233,23 +234,27 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { // Then if deleting those packets doesn't break 1 and 2, then go ahead and delete them. // // One assumption that we can make is that there will be packets in the queue. Because we call it while holding a locked packet - if (deleting) return; + if (deleting) return false; + // When keep_keyframes, normally only attempt clearing on video keyframes. + // If a previous clear attempt failed (clear_packets_pending_), retry on + // any video packet regardless of keyframe status. if (keep_keyframes and ! ( add_packet->packet->stream_index == video_stream_id and - add_packet->keyframe + (add_packet->keyframe or clear_packets_pending_) and (packet_counts[video_stream_id] > pre_event_video_packet_count) and *(pktQueue.begin()) != add_packet ) ) { - 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], pre_event_video_packet_count, + Debug(3, "stream index %d ?= video_stream_id %d, keyframe %d, keep_keyframes %d, pending %d, counts %d > pre_event_count %d at begin %d", + add_packet->packet->stream_index, video_stream_id, add_packet->keyframe, keep_keyframes, clear_packets_pending_, + packet_counts[video_stream_id], pre_event_video_packet_count, ( *(pktQueue.begin()) != add_packet ) ); - return; + return false; } // If analysis_it isn't at the end, we need to keep that many additional packets @@ -303,8 +308,9 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { } // end while Debug(3, "Done removing %d packets from queue. packet_counts %d >? pre_event %d + tail %d = %d", packets_removed, packet_counts[video_stream_id], pre_event_video_packet_count, tail_count, pre_event_video_packet_count + tail_count); + clear_packets_pending_ = (packets_removed == 0); // mutex released here at end of scope, packets destroyed after - return; + return (packets_removed > 0); } auto it = pktQueue.begin(); @@ -314,7 +320,7 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { std::shared_ptr zm_packet = *it; if (zm_packet == add_packet) { Debug(1, "First packet in queue is the analysis packet."); - return; + return false; } int keyframe_interval_count = 0; @@ -323,7 +329,8 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { if (zm_packet->queue_index >= min_iterator_queue_index) { Debug(3, "Found iterator 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); - return; + clear_packets_pending_ = true; + return false; } ++it; @@ -382,11 +389,15 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { packet_counts[zm_packet->packet->stream_index] -= 1; packets_to_destroy.push_back(std::move(zm_packet)); } - } // end if have at least max_video_packet_count video packets remaining + clear_packets_pending_ = false; + } else { + clear_packets_pending_ = true; + } } // end scope for unique_lock — mutex released here // packets_to_destroy goes out of scope here, destroying packets without holding the mutex -} // end void PacketQueue::clearPackets(ZMPacket* zm_packet) + return !clear_packets_pending_; +} // end bool PacketQueue::clearPackets(ZMPacket* zm_packet) void PacketQueue::stop() { std::lock_guard lck(mutex); diff --git a/src/zm_packetqueue.h b/src/zm_packetqueue.h index 137a7f4bb..d5e10686e 100644 --- a/src/zm_packetqueue.h +++ b/src/zm_packetqueue.h @@ -53,6 +53,7 @@ class PacketQueue { bool has_out_of_order_packets_; int max_keyframe_interval_; int frames_since_last_keyframe_; + bool clear_packets_pending_; uint64_t next_queue_index_; Monitor *monitor_; @@ -80,7 +81,7 @@ class PacketQueue { return has_out_of_order_packets_; }; int get_max_keyframe_interval() const { return max_keyframe_interval_; }; - void clearPackets(const std::shared_ptr &packet); + bool clearPackets(const std::shared_ptr &packet); int packet_count(int stream_id); bool increment_it(packetqueue_iterator *it, bool wait);