From 276b90b3ece4a4913bf40b8bce07802a255e72cf Mon Sep 17 00:00:00 2001 From: El Date: Thu, 26 Feb 2026 09:41:07 +0000 Subject: [PATCH] VNC-151 Fixed fallbac logic --- common/rfb/EncodeManager.cxx | 3 +- common/rfb/encoders/ScreenEncoderManager.cxx | 45 +++++++++++++------- common/rfb/encoders/ScreenEncoderManager.h | 7 +-- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx index db6be30..18ad342 100644 --- a/common/rfb/EncodeManager.cxx +++ b/common/rfb/EncodeManager.cxx @@ -505,7 +505,8 @@ bool EncodeManager::updateVideo(const Region &changed, const ScreenSet &layout, return false; static const Palette palette; - screen_encoder_manager->writeRect(pb, palette); + if (!screen_encoder_manager->writeFrame(pb, palette)) + return false; std::vector rects; changed.get_rects(&rects); diff --git a/common/rfb/encoders/ScreenEncoderManager.cxx b/common/rfb/encoders/ScreenEncoderManager.cxx index 2ae6537..7a97bff 100644 --- a/common/rfb/encoders/ScreenEncoderManager.cxx +++ b/common/rfb/encoders/ScreenEncoderManager.cxx @@ -30,7 +30,7 @@ namespace rfb { static LogWriter vlog("ScreenEncoderManager"); template - ScreenEncoderManager::ScreenEncoderManager(const FFmpeg &ffmpeg_, KasmVideoEncoders::EncoderConfig encoder, + ScreenEncoderManager::ScreenEncoderManager(const FFmpeg &ffmpeg_, const KasmVideoEncoders::EncoderConfig &encoder, const KasmVideoEncoders::EncoderConfigs &encoders, SConnection *conn, VideoEncoderParams params) : Encoder(conn, encodingKasmVideo, static_cast(EncoderUseNativePF | EncoderLossy), -1), ffmpeg(ffmpeg_), @@ -55,7 +55,7 @@ namespace rfb { } template - void ScreenEncoderManager::set_params(KasmVideoEncoders::EncoderConfig encoder, + void ScreenEncoderManager::set_params(const KasmVideoEncoders::EncoderConfig &encoder, const KasmVideoEncoders::EncoderConfigs &encoders, VideoEncoderParams params) { base_video_encoder = encoder; available_encoders = encoders; @@ -109,9 +109,9 @@ namespace rfb { delete screens[index].encoder; screens[index].encoder = nullptr; - mask &= ~(1 << index); --count; } + mask &= ~(1 << index); screens[index] = {}; } @@ -131,8 +131,12 @@ namespace rfb { template void ScreenEncoderManager::clear_screens() { - for (uint8_t i = 0; i < get_screen_count(); ++i) - remove_screen(i); + uint64_t remaining_mask = mask; + while (remaining_mask) { + const auto pos = __builtin_ctzll(remaining_mask); + remove_screen(pos); + remaining_mask &= remaining_mask - 1; + } } template @@ -149,8 +153,8 @@ namespace rfb { for (uint8_t i = 0; i < static_cast(layout.num_screens()); ++i) { const auto &screen = layout.screens[i]; auto id = screen.id; - if (id > T) { - vlog.error("Wrong id"); + if (id >= T) { + vlog.error("Wrong id"); id = 0; } @@ -178,21 +182,16 @@ namespace rfb { } template - void ScreenEncoderManager::writeRect(const PixelBuffer *pb, const Palette &palette) { - // if (!pb) { - // vlog.error("writeRect called with null PixelBuffer"); - // return; - // } - + bool ScreenEncoderManager::writeFrame(const PixelBuffer *pb, const Palette &palette) { if (screens_to_refresh.empty()) - return; + return true; const auto bpp = conn->cp.pf().bpp >> 3; auto *out_conn = conn->getOutStream(conn->cp.supportsUdp); if (!out_conn) { vlog.error("writeRect: getOutStream returned NULL"); - return; + return false; } const auto send_frame = [this, &bpp, out_conn, pb, &palette](screen_t &screen) { @@ -218,13 +217,23 @@ namespace rfb { }; if (screens_to_refresh.size() > 1) { - tbb::parallel_for_each(screens_to_refresh.begin(), screens_to_refresh.end(), [this, pb, &send_frame](uint8_t index) { + tbb::task_group_context ctx; + + tbb::parallel_for_each(screens_to_refresh.begin(), screens_to_refresh.end(), [this, pb, &ctx](uint8_t index) { + if (ctx.is_group_execution_cancelled()) + return; + auto &screen = screens[index]; if (auto *encoder = screen.encoder; encoder) { screen.dirty = encoder->render(pb); + if (!screen.dirty) + ctx.cancel_group_execution(); } }); + if (ctx.is_group_execution_cancelled()) + return false; + for (auto index: screens_to_refresh) { auto &screen = screens[index]; if (screen.dirty) { @@ -235,8 +244,12 @@ namespace rfb { if (auto encoder = screens[head].encoder; encoder) { if (encoder->render(pb)) send_frame(screens[head]); + else + return false; } } + + return true; } template diff --git a/common/rfb/encoders/ScreenEncoderManager.h b/common/rfb/encoders/ScreenEncoderManager.h index deda268..4465efe 100644 --- a/common/rfb/encoders/ScreenEncoderManager.h +++ b/common/rfb/encoders/ScreenEncoderManager.h @@ -83,7 +83,7 @@ namespace rfb { return screens.end(); } - explicit ScreenEncoderManager(const FFmpeg &ffmpeg_, KasmVideoEncoders::EncoderConfig encoder, + explicit ScreenEncoderManager(const FFmpeg &ffmpeg_, const KasmVideoEncoders::EncoderConfig &encoder, const KasmVideoEncoders::EncoderConfigs &encoders, SConnection *conn, VideoEncoderParams params); ~ScreenEncoderManager() override; @@ -93,7 +93,7 @@ namespace rfb { ScreenEncoderManager &operator=(ScreenEncoderManager &&) = delete; void clear(); - void set_params(KasmVideoEncoders::EncoderConfig encoder, const KasmVideoEncoders::EncoderConfigs &encoders, + void set_params(const KasmVideoEncoders::EncoderConfig &encoder, const KasmVideoEncoders::EncoderConfigs &encoders, VideoEncoderParams params); bool sync_layout(const ScreenSet &layout, const Region ®ion); @@ -104,7 +104,8 @@ namespace rfb { // Encoder [[nodiscard]] bool isSupported() const override; - void writeRect(const PixelBuffer *pb, const Palette &palette) override; + bool writeFrame(const PixelBuffer *pb, const Palette &palette); + void writeRect(const PixelBuffer *pb, const Palette &palette) override {} void writeSolidRect(int width, int height, const PixelFormat &pf, const rdr::U8 *colour) override; private: