diff --git a/src/zm_analysis_thread.cpp b/src/zm_analysis_thread.cpp index 1793b3b0f..1118d1f52 100644 --- a/src/zm_analysis_thread.cpp +++ b/src/zm_analysis_thread.cpp @@ -34,10 +34,11 @@ void AnalysisThread::Run() { // Some periodic updates are required for variable capturing framerate if (!monitor_->Analyse()) { if (!(terminate_ or zm_terminate)) { - // We only sleep when Analyse returns false because it is an error condition and we will spin like mad if it persists. - Microseconds sleep_for = monitor_->Active() ? Microseconds(ZM_SAMPLE_RATE) : Microseconds(ZM_SUSPENDED_RATE); - Debug(5, "Sleeping for %" PRId64 "us", int64(sleep_for.count())); - std::this_thread::sleep_for(sleep_for); + // We wait on the packetqueue condition variable instead of sleeping. + // This allows us to wake up immediately when decoding completes. + Microseconds wait_for = monitor_->Active() ? Microseconds(ZM_SAMPLE_RATE) : Microseconds(ZM_SUSPENDED_RATE); + Debug(5, "Waiting for %" PRId64 "us", int64(wait_for.count())); + monitor_->GetPacketQueue()->wait_for(wait_for); } } } diff --git a/src/zm_decoder_thread.cpp b/src/zm_decoder_thread.cpp index 952c63c43..6b08efd39 100644 --- a/src/zm_decoder_thread.cpp +++ b/src/zm_decoder_thread.cpp @@ -34,10 +34,11 @@ void DecoderThread::Run() { while (!(terminate_ or zm_terminate)) { if (!monitor_->Decode()) { if (!(terminate_ or zm_terminate)) { - // We only sleep when Decode returns false because it is an error condition and we will spin like mad if it persists. - Microseconds sleep_for = monitor_->Active() ? Microseconds(ZM_SAMPLE_RATE) : Microseconds(ZM_SUSPENDED_RATE); - Debug(2, "Sleeping for %" PRId64 "us", int64(sleep_for.count())); - std::this_thread::sleep_for(sleep_for); + // We wait on the packetqueue condition variable instead of sleeping. + // This allows us to wake up immediately when new packets are queued. + Microseconds wait_for = monitor_->Active() ? Microseconds(ZM_SAMPLE_RATE) : Microseconds(ZM_SUSPENDED_RATE); + Debug(2, "Waiting for %" PRId64 "us", int64(wait_for.count())); + monitor_->GetPacketQueue()->wait_for(wait_for); } } } diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index a0a937e68..b2ba61b11 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -2927,6 +2927,7 @@ bool Monitor::Decode() { if (packet->codec_type != AVMEDIA_TYPE_VIDEO) { Debug(3, "Audio packet %d, marking decoded", packet->image_index); packet->decoded = true; + packetqueue.notify_all(); // Wake up analysis thread packetqueue.increment_it(decoder_it, !decoder_queue.empty()); return true; } @@ -3029,6 +3030,7 @@ bool Monitor::Decode() { if (deinterlacing_value) { if (!applyDeinterlacing(packet, capture_image)) { packet->decoded = true; + packetqueue.notify_all(); // Wake up analysis thread return false; } } @@ -3064,6 +3066,7 @@ bool Monitor::Decode() { } packet->decoded = true; + packetqueue.notify_all(); // Wake up analysis thread waiting for decoded packets return true; } diff --git a/src/zm_packetqueue.cpp b/src/zm_packetqueue.cpp index 30df97edb..3ba0f2dce 100644 --- a/src/zm_packetqueue.cpp +++ b/src/zm_packetqueue.cpp @@ -792,3 +792,8 @@ void PacketQueue::wait() { std::unique_lock lck(mutex); condition.wait(lck); } + +void PacketQueue::wait_for(Microseconds duration) { + std::unique_lock lck(mutex); + condition.wait_for(lck, duration); +} diff --git a/src/zm_packetqueue.h b/src/zm_packetqueue.h index 842e4b37b..d41e9ad03 100644 --- a/src/zm_packetqueue.h +++ b/src/zm_packetqueue.h @@ -19,11 +19,14 @@ #ifndef ZM_PACKETQUEUE_H #define ZM_PACKETQUEUE_H +#include "zm_time.h" + #include #include #include #include +class Monitor; class ZMPacket; class ZMPacketLock; @@ -50,6 +53,7 @@ class PacketQueue { bool has_out_of_order_packets_; int max_keyframe_interval_; int frames_since_last_keyframe_; + Monitor *monitor_; public: PacketQueue(); @@ -61,6 +65,7 @@ class PacketQueue { void setMaxVideoPackets(int p); void setPreEventVideoPackets(int p); void setKeepKeyframes(bool k) { keep_keyframes = k; }; + void setMonitor(Monitor *m) { monitor_ = m; }; bool queuePacket(std::shared_ptr packet); void stop(); @@ -94,6 +99,7 @@ class PacketQueue { void unlock(ZMPacketLock *lp); void notify_all(); void wait(); + void wait_for(Microseconds duration); private: packetqueue_iterator deletePacket(packetqueue_iterator it); };