Skip to content

Commit 6310cf9

Browse files
committed
Throttle the emission of callback-updates for high number of LEDs or big images
1 parent 2e4942a commit 6310cf9

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

include/hyperion/Hyperion.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
// stl includes
44
#include <list>
5+
#include <chrono>
56

67
// QT includes
78
#include <QString>
@@ -604,4 +605,14 @@ private slots:
604605
/// Boblight instance
605606
BoblightServer* _boblightServer;
606607
#endif
608+
609+
QElapsedTimer _imageTimer; // Timer for controlling image emission frequency
610+
QElapsedTimer _rawLedDataTimer; // Timer for controlling rawLedColors emission frequency
611+
QElapsedTimer _ledDeviceDataTimer; // Timer for controlling LedDevice data emission frequency
612+
qint64 _lastImageEmission; // Last timestamp of image signal emission
613+
qint64 _lastRawLedDataEmission; // Last timestamp of rawLedColors signal emission
614+
qint64 _lastLedDeviceDataEmission; // Last timestamp of ledDeviceData signal emission
615+
std::chrono::milliseconds _imageEmissionInterval;
616+
std::chrono::milliseconds _rawLedDataEmissionInterval;
617+
std::chrono::milliseconds _ledDeviceDataEmissionInterval;
607618
};

libsrc/hyperion/Hyperion.cpp

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@
4949
#include <boblightserver/BoblightServer.h>
5050
#endif
5151

52+
// Constants
53+
namespace {
54+
constexpr std::chrono::milliseconds DEFAULT_MAX_IMAGE_EMISSION_INTERVAL{ 40 }; // 25 Hz
55+
constexpr std::chrono::milliseconds DEFAULT_MAX_RAW_LED_DATA_EMISSION_INTERVAL{ 25 }; // 40 Hz
56+
constexpr std::chrono::milliseconds DEFAULT_MAX_LED_DEVICE_DATA_EMISSION_INTERVAL{ 5 }; // 200 Hz
57+
} //End of constants
58+
5259
Hyperion::Hyperion(quint8 instance)
5360
: QObject()
5461
, _instIndex(instance)
@@ -75,6 +82,12 @@ Hyperion::Hyperion(quint8 instance)
7582
#if defined(ENABLE_BOBLIGHT_SERVER)
7683
, _boblightServer(nullptr)
7784
#endif
85+
, _lastImageEmission(0)
86+
, _lastRawLedDataEmission(0)
87+
, _lastLedDeviceDataEmission(0)
88+
, _imageEmissionInterval(DEFAULT_MAX_IMAGE_EMISSION_INTERVAL)
89+
, _rawLedDataEmissionInterval(DEFAULT_MAX_RAW_LED_DATA_EMISSION_INTERVAL)
90+
, _ledDeviceDataEmissionInterval(DEFAULT_MAX_LED_DEVICE_DATA_EMISSION_INTERVAL)
7891
{
7992
qRegisterMetaType<ComponentList>("ComponentList");
8093

@@ -109,6 +122,8 @@ void Hyperion::start()
109122
// handle hwLedCount
110123
_hwLedCount = getSetting(settings::DEVICE).object()["hardwareLedCount"].toInt(getLedCount());
111124

125+
126+
112127
// Initialize colororder vector
113128
for (const Led& led : _ledString.leds())
114129
{
@@ -180,6 +195,15 @@ void Hyperion::start()
180195
connect(GlobalSignals::getInstance(), &GlobalSignals::setGlobalColor, this, &Hyperion::setColor);
181196
connect(GlobalSignals::getInstance(), &GlobalSignals::setGlobalImage, this, &Hyperion::setInputImage);
182197

198+
// Limit LED data emission, if high rumber of LEDs configured
199+
_rawLedDataEmissionInterval = (_ledString.leds().size() > 1000) ? 2 * DEFAULT_MAX_RAW_LED_DATA_EMISSION_INTERVAL : DEFAULT_MAX_RAW_LED_DATA_EMISSION_INTERVAL;
200+
_ledDeviceDataEmissionInterval = (_hwLedCount > 1000) ? 2 * DEFAULT_MAX_LED_DEVICE_DATA_EMISSION_INTERVAL : DEFAULT_MAX_LED_DEVICE_DATA_EMISSION_INTERVAL;
201+
202+
// Set up timers to throttle specific signals
203+
_imageTimer.start(); // Start the elapsed timer for image signal throttling
204+
_rawLedDataTimer.start(); // Start the elapsed timer for rawLedColors throttling
205+
_ledDeviceDataTimer.start(); // Start the elapsed timer for LED-Device data throttling
206+
183207
// if there is no startup / background effect and no sending capture interface we probably want to push once BLACK (as PrioMuxer won't emit a priority change)
184208
update();
185209

@@ -267,6 +291,7 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
267291
std::vector<ColorRgb> color(_ledString.leds().size(), ColorRgb{0,0,0});
268292
_ledBuffer = color;
269293

294+
270295
_ledStringColorOrder.clear();
271296
for (const Led& led : _ledString.leds())
272297
{
@@ -276,6 +301,10 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
276301
// handle hwLedCount update
277302
_hwLedCount = getSetting(settings::DEVICE).object()["hardwareLedCount"].toInt(getLedCount());
278303

304+
// Limit LED data emission, if high rumber of LEDs configured
305+
_rawLedDataEmissionInterval = (_ledString.leds().size() > 1000) ? 2 * DEFAULT_MAX_RAW_LED_DATA_EMISSION_INTERVAL : DEFAULT_MAX_RAW_LED_DATA_EMISSION_INTERVAL;
306+
_ledDeviceDataEmissionInterval = (_hwLedCount > 1000) ? 2 * DEFAULT_MAX_LED_DEVICE_DATA_EMISSION_INTERVAL : DEFAULT_MAX_LED_DEVICE_DATA_EMISSION_INTERVAL;
307+
279308
// change in leds are also reflected in adjustment
280309
delete _raw2ledAdjustment;
281310
_raw2ledAdjustment = hyperion::createLedColorsAdjustment(static_cast<int>(_ledString.leds().size()), getSetting(settings::COLOR).object());
@@ -672,7 +701,14 @@ void Hyperion::update()
672701
Image<ColorRgb> image = priorityInfo.image;
673702
if (image.width() > 1 || image.height() > 1)
674703
{
675-
emit currentImage(image);
704+
_imageEmissionInterval = (image.width() > 1280) ? 2 * DEFAULT_MAX_IMAGE_EMISSION_INTERVAL : DEFAULT_MAX_IMAGE_EMISSION_INTERVAL;
705+
// Throttle the emission of currentImage(image) signal
706+
qint64 elapsedImageEmissionTime = _imageTimer.elapsed();
707+
if (elapsedImageEmissionTime - _lastImageEmission >= _imageEmissionInterval.count())
708+
{
709+
_lastImageEmission = elapsedImageEmissionTime;
710+
emit currentImage(image); // Emit the image signal at the controlled rate
711+
}
676712
_ledBuffer = _imageProcessor->process(image);
677713
}
678714
else
@@ -692,9 +728,15 @@ void Hyperion::update()
692728
}
693729
}
694730

695-
// emit rawLedColors before transform
696-
emit rawLedColors(_ledBuffer);
731+
// Throttle the emission of rawLedColors(_ledBuffer) signal
732+
qint64 elapsedRawLedDataEmissionTime = _rawLedDataTimer.elapsed();
733+
if (elapsedRawLedDataEmissionTime - _lastRawLedDataEmission >= _rawLedDataEmissionInterval.count())
734+
{
735+
_lastRawLedDataEmission = elapsedRawLedDataEmissionTime;
736+
emit rawLedColors(_ledBuffer); // Emit the rawLedColors signal at the controlled rate
737+
}
697738

739+
// Start transformations
698740
_raw2ledAdjustment->applyAdjustment(_ledBuffer);
699741

700742
int i = 0;
@@ -740,7 +782,13 @@ void Hyperion::update()
740782
// Smoothing is disabled
741783
if (! _deviceSmooth->enabled())
742784
{
743-
emit ledDeviceData(_ledBuffer);
785+
// Throttle the emission of LED-Device data signal
786+
qint64 elapsedLedDeviceDataEmissionTime = _ledDeviceDataTimer.elapsed();
787+
if (elapsedLedDeviceDataEmissionTime - _lastLedDeviceDataEmission >= _ledDeviceDataEmissionInterval.count())
788+
{
789+
_lastLedDeviceDataEmission = elapsedLedDeviceDataEmissionTime;
790+
emit ledDeviceData(_ledBuffer);
791+
}
744792
}
745793
else
746794
{

0 commit comments

Comments
 (0)