Merge branch 'release-1.36' of github.com:ZoneMinder/zoneminder into release-1.36

pull/3609/head
Isaac Connor 2022-08-12 17:59:09 -04:00
commit af4f8fd761
3 changed files with 43 additions and 16 deletions

View File

@ -1824,13 +1824,13 @@ bool Monitor::Analyse() {
/* try to stay behind the decoder. */
if (decoding_enabled) {
while (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) {
while (!snap->decoded and !zm_terminate and !analysis_thread->Stopped() and !packetqueue.stopping()) {
// Need to wait for the decoder thread.
packetqueue.notify_all();
Debug(1, "Waiting for decode");
packet_lock->wait();
} // end while ! decoded
if (zm_terminate or analysis_thread->Stopped()) {
if (zm_terminate or analysis_thread->Stopped() or packetqueue.stopping()) {
delete packet_lock;
return false;
}

View File

@ -33,7 +33,9 @@ PacketQueue::PacketQueue():
packet_counts(nullptr),
deleting(false),
keep_keyframes(false),
warned_count(0)
warned_count(0),
has_out_of_order_packets_(false),
max_keyframe_interval_(0)
{
}
@ -86,6 +88,24 @@ bool PacketQueue::queuePacket(std::shared_ptr<ZMPacket> add_packet) {
}
{
std::unique_lock<std::mutex> lck(mutex);
if (deleting or zm_terminate) return false;
if (!has_out_of_order_packets_ and (add_packet->packet.dts != AV_NOPTS_VALUE)) {
auto rit = pktQueue.rbegin();
// Find the previous packet for the stream, and check dts
while (rit != pktQueue.rend()) {
if ((*rit)->packet.stream_index == add_packet->packet.stream_index) {
if ((*rit)->packet.dts >= add_packet->packet.dts) {
Debug(1, "Have out of order packets");
ZM_DUMP_PACKET((*rit)->packet, "queued_packet");
ZM_DUMP_PACKET(add_packet->packet, "add_packet");
has_out_of_order_packets_ = true;
}
break;
}
rit++;
} // end while
}
pktQueue.push_back(add_packet);
packet_counts[add_packet->packet.stream_index] += 1;
@ -115,8 +135,8 @@ bool PacketQueue::queuePacket(std::shared_ptr<ZMPacket> add_packet) {
warned_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);
" your camera's keyframe interval %d is larger than this setting."
, max_video_packet_count, max_keyframe_interval_);
}
for (
@ -152,6 +172,9 @@ bool PacketQueue::queuePacket(std::shared_ptr<ZMPacket> add_packet) {
}
} // end foreach iterator
zm_packet->decoded = true; // Have to in case analysis is waiting on it
zm_packet->notify_all();
it = pktQueue.erase(it);
packet_counts[zm_packet->packet.stream_index] -= 1;
Debug(1,
@ -226,12 +249,8 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
// 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] > pre_event_video_packet_count + tail_count)) {
std::shared_ptr<ZMPacket> zm_packet = *pktQueue.begin();
ZMLockedPacket *lp = new ZMLockedPacket(zm_packet);
if (!lp->trylock()) {
delete lp;
break;
}
delete lp;
ZMLockedPacket lp(zm_packet);
if (!lp.trylock()) break;
if (is_there_an_iterator_pointing_to_packet(zm_packet)) {
Warning("Found iterator at beginning of queue. Some thread isn't keeping up");
@ -297,12 +316,12 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
}
#endif
if (zm_packet->packet->stream_index == video_stream_id) {
if (zm_packet->packet.stream_index == video_stream_id) {
keyframe_interval_count++;
if (zm_packet->keyframe) {
Debug(4, "Have a video keyframe so setting next front to it. Keyframe interval so far is %d", keyframe_interval_count);
if (max_keyframe_interval < keyframe_interval_count) max_keyframe_interval = keyframe_interval_count;
Debug(3, "Have a video keyframe so setting next front to it. Keyframe interval so far is %d", keyframe_interval_count);
if (keyframe_interval_count > max_keyframe_interval_)
max_keyframe_interval_ = keyframe_interval_count;
keyframe_interval_count = 1;
next_front = it;
}
@ -353,11 +372,14 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
void PacketQueue::stop() {
deleting = true;
condition.notify_all();
for (const auto &p : pktQueue) p->notify_all();
for (const auto &p : pktQueue) {
p->notify_all();
}
}
void PacketQueue::clear() {
deleting = true;
// Why are we notifying?
condition.notify_all();
if (!packet_counts) // special case, not initialised
return;

View File

@ -47,6 +47,8 @@ class PacketQueue {
std::mutex mutex;
std::condition_variable condition;
int warned_count;
bool has_out_of_order_packets_;
int max_keyframe_interval_;
public:
PacketQueue();
@ -61,10 +63,13 @@ class PacketQueue {
bool queuePacket(std::shared_ptr<ZMPacket> packet);
void stop();
bool stopping() const { return deleting; };
void clear();
void dumpQueue();
unsigned int size();
unsigned int get_packet_count(int stream_id) const { return packet_counts[stream_id]; };
bool has_out_of_order_packets() const { return has_out_of_order_packets_; };
int get_max_keyframe_interval() const { return max_keyframe_interval_; };
void clearPackets(const std::shared_ptr<ZMPacket> &packet);
int packet_count(int stream_id);