[plasma/krdp] src: VideoStream: remove the RTT-based source-rate heuristic
Nate Graham <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 978f1cb7e020d96a274947b08caae2b14f7533f3 by Nate Graham, on behalf of Shouvik Kar.
Committed on 06/08/2026 at 13:37.
Pushed by ngraham into branch 'master'.
VideoStream: remove the RTT-based source-rate heuristic
updateRequestedFrameRate() lowered the source/encoder cap from an averageRTT x
frameDelay estimate. On high-latency links it collapses the requested rate to
1-5 fps even when there is no real send-side pressure, starving throughput.
Remove it and its state; the requested frame rate stays at the client-configured
value. The fixed in-flight window (MaximumInFlightFrames = 2) is unchanged --
high-RTT throughput is still capped until a later commit sizes the window from RTT.
M +0 -64 src/VideoStream.cpp
M +0 -2 src/VideoStream.h
https://invent.kde.org/plasma/krdp/-/commit/978f1cb7e020d96a274947b08caae2b14f7533f3
diff --git a/src/VideoStream.cpp b/src/VideoStream.cpp
index ddc3d2c..0bdc35c 100644
--- a/src/VideoStream.cpp
+++ b/src/VideoStream.cpp
@@ -36,7 +36,6 @@ namespace KRdp
namespace clk = std::chrono;
// Maximum number of frames to contain in the queue.
-constexpr clk::system_clock::duration FrameRateEstimateAveragePeriod = clk::seconds(1);
constexpr qsizetype MaximumInFlightFrames = 2;
constexpr uint32_t ProgressiveCodecContextId = 1;
struct RdpCapsInformation {
@@ -106,11 +105,6 @@ struct Surface {
QSize size;
};
-struct FrameRateEstimate {
- clk::system_clock::time_point timeStamp;
- int estimate = 0;
-};
-
class KRDP_NO_EXPORT VideoStream::Private
{
public:
@@ -151,13 +145,7 @@ public:
std::mutex pendingFramesMutex;
- int maximumFrameRate = 120;
std::atomic_int requestedFrameRate = 60;
- QQueue<FrameRateEstimate> frameRateEstimates;
- clk::system_clock::time_point lastFrameRateEstimation;
-
- std::atomic_int encodedFrames = 0;
- std::atomic_int frameDelay = 0;
bool initialized = false;
quint8 quality = 100;
@@ -364,8 +352,6 @@ bool VideoStream::initialize()
d->initialized = true;
- connect(d->session->networkDetection(), &NetworkDetection::rttChanged, this, &VideoStream::updateRequestedFrameRate);
-
d->frameSubmissionThread = std::jthread([this](std::stop_token token) {
while (!token.stop_requested()) {
if (!hasInFlightCapacity() || !d->gfxContext || !d->capsConfirmed) {
@@ -676,7 +662,6 @@ uint32_t VideoStream::onFrameAcknowledge(const RDPGFX_FRAME_ACKNOWLEDGE_PDU *fra
return CHANNEL_RC_OK;
}
- d->frameDelay = d->encodedFrames - frameAcknowledge->totalFramesDecoded;
d->pendingFrames.erase(itr);
return CHANNEL_RC_OK;
@@ -882,8 +867,6 @@ void VideoStream::sendFrameH264(const VideoFrame &frame)
auto frameId = d->frameId++;
- d->encodedFrames++;
-
{
std::lock_guard lock(d->pendingFramesMutex);
d->pendingFrames.insert(frameId);
@@ -992,8 +975,6 @@ void VideoStream::sendFrameProgressive(const VideoFrame &frame)
auto frameId = d->frameId++;
- d->encodedFrames++;
-
{
std::lock_guard lock(d->pendingFramesMutex);
d->pendingFrames.insert(frameId);
@@ -1034,51 +1015,6 @@ void VideoStream::sendFrameProgressive(const VideoFrame &frame)
d->session->networkDetection()->stopBandwidthMeasure();
region16_uninit(&*invalidRegion);
}
-
-void VideoStream::updateRequestedFrameRate()
-{
- auto rtt = std::max(clk::duration_cast<clk::milliseconds>(d->session->networkDetection()->averageRTT()), clk::milliseconds(1));
- auto now = clk::system_clock::now();
-
- FrameRateEstimate estimate;
- estimate.timeStamp = now;
- estimate.estimate = std::min(int(clk::milliseconds(1000) / (rtt * std::max(d->frameDelay.load(), 1))), d->maximumFrameRate);
- d->frameRateEstimates.append(estimate);
-
- if (now - d->lastFrameRateEstimation < FrameRateEstimateAveragePeriod) {
- return;
- }
-
- d->lastFrameRateEstimation = now;
-
- d->frameRateEstimates.erase(std::remove_if(d->frameRateEstimates.begin(),
- d->frameRateEstimates.end(),
- [now](const auto &estimate) {
- return (estimate.timeStamp - now) > FrameRateEstimateAveragePeriod;
- }),
- d->frameRateEstimates.cend());
-
- auto sum = std::accumulate(d->frameRateEstimates.cbegin(), d->frameRateEstimates.cend(), 0, [](int acc, const auto &estimate) {
- return acc + estimate.estimate;
- });
- auto average = sum / d->frameRateEstimates.size();
-
- // we want some headroom so we can always clear our current load
- // and handle any other latency
- constexpr qreal targetFrameRateSaturation = 0.5;
- auto frameRate = std::max(1.0, average * targetFrameRateSaturation);
-
- if (frameRate != d->requestedFrameRate) {
- d->requestedFrameRate = frameRate;
- if (d->encodedStream) {
- d->encodedStream->setMaxFramerate(frameRate, 1);
- d->encodedStream->setMaxPendingFrames(frameRate);
- }
- if (d->sourceStream) {
- d->sourceStream->setMaxFramerate({static_cast<quint32>(frameRate), 1});
- }
- }
-}
}
#include "moc_VideoStream.cpp"
diff --git a/src/VideoStream.h b/src/VideoStream.h
index de91425..a84738f 100644
--- a/src/VideoStream.h
+++ b/src/VideoStream.h
@@ -108,8 +108,6 @@ private:
void sendFrameH264(const VideoFrame &frame);
void sendFrameProgressive(const VideoFrame &frame);
- void updateRequestedFrameRate();
-
class Private;
const std::unique_ptr<Private> d;
};